zest.core
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/META-INF/MANIFEST.MF b/visualization/plugins/org.eclipse.mylar.zest.core/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..bf1db02
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/META-INF/MANIFEST.MF
@@ -0,0 +1,30 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Core Plug-in
+Bundle-SymbolicName: org.eclipse.mylar.zest.core; singleton:=true
+Bundle-Version: 0.3.1
+Bundle-Activator: org.eclipse.mylar.zest.core.ZestPlugin
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.mylar.zest.layouts,
+ org.eclipse.gef
+Eclipse-LazyStart: true
+Export-Package: org.eclipse.mylar.zest.core,
+ org.eclipse.mylar.zest.core.internal.gefx;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.internal.graphmodel;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.internal.graphmodel.nested;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.internal.graphviewer;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.internal.graphviewer.parts;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.internal.graphviewer.policies;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.internal.nestedgraphviewer;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.internal.nestedgraphviewer.policies;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.internal.viewers;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.internal.viewers.commands;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.internal.viewers.figures;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.internal.viewers.trackers;x-friends:="org.eclipse.mylar.zest.custom",
+ org.eclipse.mylar.zest.core.messages,
+ org.eclipse.mylar.zest.core.viewers,
+ org.eclipse.mylar.zest.core.widgets
+Import-Package: com.ibm.icu.text
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/about.html b/visualization/plugins/org.eclipse.mylar.zest.core/about.html
new file mode 100644
index 0000000..1aeb16b
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/about.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<title>About</title>
+<meta http-equiv=Content-Type content="text/html; charset=ISO-8859-1">
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+ 
+<p>May 2, 2006</p>	
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;).  Unless otherwise 
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;).  A copy of the EPL is available 
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is 
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content.  Check the Redistributor's license that was 
+provided with the Content.  If no such license exists, contact the Redistributor.  Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/build.properties b/visualization/plugins/org.eclipse.mylar.zest.core/build.properties
new file mode 100644
index 0000000..a9cbb06
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/build.properties
@@ -0,0 +1,7 @@
+bin.includes = plugin.xml,\
+               META-INF/,\
+               .,\
+               src/icons/
+jars.compile.order = .
+source.. = src/
+output.. = bin/
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/currentTasks.txt b/visualization/plugins/org.eclipse.mylar.zest.core/currentTasks.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/currentTasks.txt
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/license.txt b/visualization/plugins/org.eclipse.mylar.zest.core/license.txt
new file mode 100644
index 0000000..f61d34d
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/license.txt
@@ -0,0 +1,88 @@
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
+b) in the case of each subsequent Contributor:
+
+i) changes to the Program, and
+
+ii) additions to the Program;
+
+where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.
+
+2. GRANT OF RIGHTS
+
+a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
+
+b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
+
+c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
+
+d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:
+
+a) it complies with the terms and conditions of this Agreement; and
+
+b) its license agreement:
+
+i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
+
+ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
+
+iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
+
+iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+a) it must be made available under this Agreement; and
+
+b) a copy of this Agreement must be included with each copy of the Program.
+
+Contributors may not remove or alter any copyright notices contained within the Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
+
+ 
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/plugin.xml b/visualization/plugins/org.eclipse.mylar.zest.core/plugin.xml
new file mode 100644
index 0000000..8e49b52
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/plugin.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+
+</plugin>
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/home.gif b/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/home.gif
new file mode 100644
index 0000000..38e8b54
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/home.gif
Binary files differ
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/tree_hanging.gif b/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/tree_hanging.gif
new file mode 100644
index 0000000..9c050ed
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/tree_hanging.gif
Binary files differ
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/tree_hanging_inverse.gif b/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/tree_hanging_inverse.gif
new file mode 100644
index 0000000..22e017d
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/tree_hanging_inverse.gif
Binary files differ
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/tree_normal.gif b/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/tree_normal.gif
new file mode 100644
index 0000000..4a7cb1a
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/tree_normal.gif
Binary files differ
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/tree_normal_inverse.gif b/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/tree_normal_inverse.gif
new file mode 100644
index 0000000..2c216e7
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/icons/tree_normal_inverse.gif
Binary files differ
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/IZestColorConstants.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/IZestColorConstants.java
new file mode 100644
index 0000000..5c8f499
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/IZestColorConstants.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core;
+
+/**
+ * Provides constants for default colors used in ZEST.
+ * @author Del Myers
+ * @tag zest(bug(151332-Colors)) : resolution
+ */
+public interface IZestColorConstants {
+
+	public static final String LIGHT_BLUE = "org.eclipse.mylar.zest.colors.lightblue"; //$NON-NLS-1$
+	public static final String LIGHT_BLUE_CYAN = "org.eclipse.mylar.zest.colors.lightbluecyan"; //$NON-NLS-1$
+	public static final String GREY_BLUE = "org.eclipse.mylar.zest.colors.greyblue"; //$NON-NLS-1$
+	public static final String DARK_BLUE = "org.eclipse.mylar.zest.colors.darkblue"; //$NON-NLS-1$
+	public static final String LIGHT_YELLOW = "org.eclipse.mylar.zest.colors.lightyellow"; //$NON-NLS-1$
+	public static final String WHITE = "org.eclipse.mylar.zest.colors.white"; //$NON-NLS-1$
+	public static final String LIGHT_GRAY = "org.eclipse.mylar.zest.colors.lightgray"; //$NON-NLS-1$
+	public static final String DISABLED = "org.eclipse.mylar.zest.colors.disabled"; //$NON-NLS-1$
+	public static final String GRAY = "org.eclipse.mylar.zest.colors.gray"; //$NON-NLS-1$
+	public static final String BLACK = "org.eclipse.mylar.zest.colors.black"; //$NON-NLS-1$
+	public static final String RED = "org.eclipse.mylar.zest.colors.red"; //$NON-NLS-1$
+	public static final String DARK_RED = "org.eclipse.mylar.zest.colors.darkred";
+	public static final String ORANGE = "org.eclipse.mylar.zest.colors.orange"; //$NON-NLS-1$
+	public static final String YELLOW = "org.eclipse.mylar.zest.colors.yellow"; //$NON-NLS-1$
+	public static final String GREEN = "org.eclipse.mylar.zest.colors.green"; //$NON-NLS-1$
+	public static final String LIGHT_GREEN = "org.eclipse.mylar.zest.colors.lightgreen"; //$NON-NLS-1$
+	public static final String DARK_GREEN = "org.eclipse.mylar.zest.colors.darkgreen"; //$NON-NLS-1$
+	public static final String CYAN = "org.eclipse.mylar.zest.colors.cyan"; //$NON-NLS-1$
+	public static final String BLUE = "org.eclipse.mylar.zest.colors.blue"; //$NON-NLS-1$;
+	public static final String NODE_DEFAULT_FOREGROUND = BLACK;
+	public static final String NODE_DEFAULT_BACKGROUND = LIGHT_BLUE;
+	public static final String NODE_DEFAULT_HIGHLIGHT = YELLOW;
+	public static final String NODE_DEFAULT_ADJACENT = ORANGE;
+	public static final String NODE_DEFAULT_BORDER = BLACK;
+	public static final String NODE_DEFAULT_BORDER_HIGHLIGHT = BLUE;
+	public static final String EDGE_WEIGHT_0 = "edge.0"; //$NON-NLS-1$
+	public static final String EDGE_WEIGHT_01 = "edge.01"; //$NON-NLS-1$
+	public static final String EDGE_WEIGHT_02 = "edge.02"; //$NON-NLS-1$
+	public static final String EDGE_WEIGHT_03 = "edge.03"; //$NON-NLS-1$
+	public static final int EDGE_WEIGHTS = 4;
+	
+	public static final String EDGE_DEFAULT = "org.eclipse.mylar.zest.colors.edgedefault"; //$NON-NLS-1$
+	public static final String EDGE_HIGHLIGHT = "org.eclipse.mylar.zest.colors.edgehighlight"; //$NON-NLS-1$
+	
+	
+	
+	
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/IZestImageConstants.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/IZestImageConstants.java
new file mode 100644
index 0000000..971f960
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/IZestImageConstants.java
@@ -0,0 +1,9 @@
+package org.eclipse.mylar.zest.core;
+
+public interface IZestImageConstants {
+
+	public static String TREE_HANGING_ICON = "src/icons/tree_hanging.gif";
+	public static String TREE_HANGING_INVERSE_ICON = "src/icons/tree_hanging_inverse.gif";
+	public static String TREE_NORMAL_ICON = "src/icons/tree_normal.gif";
+	public static String TREE_NORMAL_INVERSE_ICON = "src/icons/tree_normal_inverse.gif";
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/ZestColors.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/ZestColors.java
new file mode 100644
index 0000000..253e250
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/ZestColors.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core;
+
+import org.eclipse.swt.graphics.Color;
+
+/**
+ * Color constants used in Zest.
+ * 
+ * @author Chris Callendar
+ * @deprecated
+ */
+public final class ZestColors {
+
+	public static final Color LIGHT_BLUE = new Color(null, 216, 228, 248);
+
+	public static final Color LIGHT_BLUE_CYAN = new Color(null, 213, 243, 255);
+	
+	public static final Color GREY_BLUE = new Color(null, 139, 150, 171);
+	
+	public static final Color DARK_BLUE = new Color(null, 1, 70, 122);
+
+	public static final Color LIGHT_YELLOW = new Color(null, 255, 255, 206);
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/ZestException.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/ZestException.java
new file mode 100644
index 0000000..6dd6981
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/ZestException.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core;
+
+import org.eclipse.mylar.zest.core.messages.ZestErrorMessages;
+
+/**
+ * Exceptions for Zest-specific code.
+ * @author Del Myers
+ *
+ */
+public class ZestException extends RuntimeException {
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	/**
+	 * An invalid input was given to a zest component.
+	 */
+	public static final int ERROR_INVALID_INPUT = 0;
+	/**
+	 * A style was set on a viewer while the input wasn't null. 
+	 */
+	public static final int ERROR_CANNOT_SET_STYLE = 1;
+	
+	/**
+	 * An invalid style was set for a part.
+	 */
+	public static final int ERROR_INVALID_STYLE = 2;
+	
+	public ZestException(String message, Throwable cause) {
+		super(message, cause);
+	}
+	
+	protected static final void throwError(int code, String info, Throwable cause) {
+		String message = "";
+		if (info == null) info = "";
+		switch(code) {
+			case ERROR_INVALID_INPUT:
+				message = ZestErrorMessages.ERROR_INVALID_INPUT;
+				break;
+			case ERROR_CANNOT_SET_STYLE:
+				message = ZestErrorMessages.ERROR_CANNOT_SET_STYLE;
+				break;
+			case ERROR_INVALID_STYLE:
+				message = ZestErrorMessages.ERROR_INVALID_STYLE;
+				break;
+			default:
+				message = info;
+				break;
+		}
+		throw new ZestException(message + ":" + info, cause);
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/ZestPlugin.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/ZestPlugin.java
new file mode 100644
index 0000000..a82fe1c
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/ZestPlugin.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core;
+
+import org.eclipse.jface.resource.ColorRegistry;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ * @author Ian Bull
+ */
+public class ZestPlugin extends AbstractUIPlugin {
+
+	//The shared instance.
+	private static ZestPlugin plugin;
+	
+	//colors used by Zest.
+	private ColorRegistry colors;
+	
+	/**
+	 * The constructor.
+	 */
+	public ZestPlugin() {
+		plugin = this;
+	}
+
+	/**
+	 * This method is called upon plug-in activation
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+		addImage(IZestImageConstants.TREE_HANGING_ICON, getImageDescriptor(IZestImageConstants.TREE_HANGING_ICON).createImage());
+		addImage(IZestImageConstants.TREE_NORMAL_ICON, getImageDescriptor(IZestImageConstants.TREE_NORMAL_ICON).createImage());
+		addImage(IZestImageConstants.TREE_HANGING_INVERSE_ICON, getImageDescriptor(IZestImageConstants.TREE_HANGING_INVERSE_ICON).createImage());
+		addImage(IZestImageConstants.TREE_NORMAL_INVERSE_ICON, getImageDescriptor(IZestImageConstants.TREE_NORMAL_INVERSE_ICON).createImage());
+
+	}
+
+	/**
+	 * This method is called when the plug-in is stopped
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		plugin = null;
+	}
+
+	/**
+	 * Returns the shared instance.
+	 */
+	public static ZestPlugin getDefault() {
+		return plugin;
+	}
+
+	/**
+	 * Returns an image descriptor for the image file at the given
+	 * plug-in relative path.
+	 *
+	 * @param path the path
+	 * @return the image descriptor
+	 */
+	public static ImageDescriptor getImageDescriptor(String path) {
+		return AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.mylar.zest.core", path);
+	 }
+	
+	public void addImage( String key, Image image )  {
+		super.createImageRegistry();
+		getImageRegistry().put(key, image);
+	}
+	
+	public void removeImage( String key ) {
+		super.createImageRegistry();
+		getImageRegistry().remove(key);
+	}
+	
+	public Image getImage( String key ) {
+		super.createImageRegistry();
+		return getImageRegistry().get(key);
+	}
+	
+	
+	/**
+	 * Gets the color registered for the given key. Keys can be found in
+	 * org.eclipse.mylar.zest.core.IZestColorConstants.
+	 * @param key the key used to reference the color.
+	 * @return the color, or null if no color can be found.
+	 * @see org.eclipse.mylar.zest.core.IZestColorConstants.
+	 */ 
+	 //@tag zest(bug(151332-Colors)) : resolution
+	public Color getColor(String key) {
+		if (colors == null) {
+			Display display = getWorkbench().getDisplay();
+			colors = new ColorRegistry(display);
+			populateColors(colors);
+		}
+		return colors.get(key);
+	}
+	
+	/**
+	 * Sends an error from the ZestPlugin.
+	 * @param code the error code.
+	 * @see #ZestException
+	 */
+	public static void error(int code) {
+		ZestException.throwError(code, "", null);
+	}
+
+	private void populateColors(ColorRegistry colors) {
+		colors.put(IZestColorConstants.LIGHT_BLUE, new RGB(216, 228, 248));
+		colors.put(IZestColorConstants.DARK_BLUE, new RGB(1, 70, 122));
+		colors.put(IZestColorConstants.GREY_BLUE, new RGB(139, 150, 171));
+		colors.put(IZestColorConstants.LIGHT_BLUE_CYAN, new RGB(213, 243, 255));
+		colors.put(IZestColorConstants.LIGHT_YELLOW, new RGB(255, 255, 206));
+		colors.put(IZestColorConstants.GRAY, new RGB(128, 128, 128));
+		colors.put(IZestColorConstants.LIGHT_GRAY, new RGB(220, 220, 220));
+		colors.put(IZestColorConstants.BLACK, new RGB(0,0,0));
+		colors.put(IZestColorConstants.RED, new RGB(255,0,0));
+		colors.put(IZestColorConstants.DARK_RED, new RGB(127,0,0));
+		colors.put(IZestColorConstants.ORANGE, new RGB(255, 196, 0));
+		colors.put(IZestColorConstants.YELLOW, new RGB(255,255,0));
+		colors.put(IZestColorConstants.GREEN, new RGB(0,255,0));
+		colors.put(IZestColorConstants.DARK_GREEN, new RGB(0,127,0));
+		colors.put(IZestColorConstants.LIGHT_GREEN, new RGB(96,255,96));
+		colors.put(IZestColorConstants.CYAN, new RGB(0,255,255));
+		colors.put(IZestColorConstants.BLUE, new RGB(0,0,255));
+		colors.put(IZestColorConstants.DARK_BLUE, new RGB(0,0,127));
+		colors.put(IZestColorConstants.WHITE, new RGB(255,255,255));
+		colors.put(IZestColorConstants.EDGE_WEIGHT_0, new RGB(192, 192, 255));
+		colors.put(IZestColorConstants.EDGE_WEIGHT_01, new RGB(64, 128, 225));
+		colors.put(IZestColorConstants.EDGE_WEIGHT_02, new RGB(32, 32, 128));
+		colors.put(IZestColorConstants.EDGE_WEIGHT_03, new RGB(0, 0, 128));
+		colors.put(IZestColorConstants.EDGE_DEFAULT, new RGB(64, 64, 128));
+		colors.put(IZestColorConstants.EDGE_HIGHLIGHT, new RGB(192, 32, 32));
+		colors.put(IZestColorConstants.DISABLED,new RGB(230, 240, 250));
+		
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/ZestStyles.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/ZestStyles.java
new file mode 100644
index 0000000..a78d029
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/ZestStyles.java
@@ -0,0 +1,295 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core;
+
+import org.eclipse.mylar.zest.core.viewers.IConnectionStyleBezierExtension;
+
+/**
+ * Style constants used in Zest.
+ * 
+ * @author Chris Callendar
+ */
+public final class ZestStyles {
+
+	/**
+	 * A constant known to be zero (0), used in operations which
+	 * take bit flags to indicate that "no bits are set".
+	 */
+	//@tag style(graph)
+	public static final int NONE = 0;
+
+	/** 
+	 * Style constant indicating if marquee selection (multiple selection) 
+	 * is allowed. 
+	 */
+	//@tag style(graph)
+	public static final int MARQUEE_SELECTION = 1 << 0;
+	
+	/** 
+	 * Style constant indicating if panning (moving root edit part canvas) is allowed.  
+	 * You cannot have marquee selection and panning enabled at the same time.
+	 */
+	//@tag style(graph)
+	public static final int PANNING = 1 << 1;
+	
+	/** 
+	 * Style constant for nested graphs which indicates that real zooming 
+	 * will be done when navigating in or out of nodes.
+	 */
+	//@tag style(graph(later))
+	public static final int ZOOM_REAL = 1 << 5;
+	
+	/** 
+	 * Style constant for nested graphs which indicates that expand and collapse zooming 
+	 * will be done when navigating in or out of nodes.  This is not real zooming, instead
+	 * the nodes will expand to fill the area giving the impression of zooming. 
+	 */
+	//@tag style(graph(later))
+	public static final int ZOOM_EXPAND = 1 << 6;
+	
+	/** 
+	 * Style constant for nested graphs which indicates that fake zooming 
+	 * will be done when navigating in or out of nodes.  This consists of a 
+	 * dotted rectangle expanding to fill the area when zooming in, or a rectangle shrinking
+	 * down to the size of the node.
+	 */
+	//@tag style(graph(later))
+	public static final int ZOOM_FAKE = 1 << 7;
+	
+	
+	/** 
+	 * A style constant which indicates that nodes aren't 
+	 * allowed to overlap. Note: this is a hint.
+	 */
+	//@tag style(graph(hint))
+	public static final int NO_OVERLAPPING_NODES = 1 << 10;
+	
+	/** 
+	 * Style constant indicating whether figures can be moved outside the bounding
+	 * rectangle.  If enforce bounds is not set then scrollbars will probably be used.
+	 */ 
+	//@tag style(graph)
+	public static final int ENFORCE_BOUNDS = 1 << 11;
+	
+	/**
+	 * Style constant indicating that invisible nodes should be ignored for layouts.
+	 */
+	//@tag style.graph
+	public static final int IGNORE_INVISIBLE_LAYOUT = 1 << 12;
+	
+	/** 
+	 * Style constant indicating if the selected node's neighbors 
+	 * should be highlighted. Note: this is a node-level style. It should not
+	 * be applied to graph views during construction.
+	 * @see  
+	 */
+	//@tag style(node)
+	public static final int NODES_HIGHLIGHT_ADJACENT = 1 << 1;
+	
+	/**
+	 * Style constant indicating that node labels should be cached.
+	 * This is important under GTK+ because font drawing is slower than Windows.
+	 */
+	public static final int NODES_CACHE_LABEL = 1 << 2;
+
+	
+	
+	/**
+	 * Style indicating that connections should show their direction by default.
+	 */
+	//@tag style(edge) : use a new name... this may be useful later for algorithms.
+	public static final int CONNECTIONS_DIRECTED = 1 << 5;
+	
+	/**
+	 * Style indicating that the arrow indicating the direction of the connection
+	 * should be open.
+	 */
+	//@tag style(edge)
+	public static final int CONNECTIONS_OPEN = 1 << 4;
+	
+	
+	/**
+	 * Style indicating that lables should be placed in the middle of connections.
+	 * This is the default.
+	 */
+	//@tag style.arcs
+	//@tag zest.bug.160368-ConnectionAlign.fix
+	public static final int CONNECTIONS_VALIGN_MIDDLE = 1 << 11;
+	
+	/**
+	 * Style indicating that labels should be placed above connections.
+	 */
+	//@tag style.arcs
+//	@tag zest.bug.160368-ConnectionAlign.fix
+	public static final int CONNECTIONS_VALIGN_TOP = 1 << 12;
+	
+	/**
+	 * Style indicating that labels should be placed below connections.
+	 */
+	//@tag style.arcs
+//	@tag zest.bug.160368-ConnectionAlign.fix
+	public static final int CONNECTIONS_VALIGN_BOTTOM = 1 << 13;
+	
+	/**
+	 * "Horizontal" alignment constant. Labels should be placed at the beginning
+	 * of the line. Figures will be anchored so that they have one end at the
+	 * beginning of the connection, not so that they are centered at the start
+	 * point. Which end of the figure is placed at that point will depend
+	 * on the direction of the first two points.
+	 */
+	public static final int CONNECTIONS_HALIGN_START = 1 << 14;
+	
+	/**
+	 * "Horizontal" alignment constant. Labels should be placed at the end of
+	 * the line. Figures will be anchored so that they have one end at the
+	 * beginning of the connection, not so that they are centered at the end
+	 * point. Which end of the figure is placed at that point will depend
+	 * on the direction of the last two points.
+	 */
+	public static final int CONNECTIONS_HALIGN_END = 1 << 15;
+	
+	/**
+	 * "Horizontal" alignment constant. Figures should be placed in the center
+	 * of the points on the line.
+	 */
+	public static final int CONNECTIONS_HALIGN_CENTER = 1 << 16;
+	
+	/**
+	 * "Horizontal" alignment constant. Labels should be centered between the
+	 * first two points on the connection. For connections with only two points, 
+	 * this will behave the same as CENTER.
+	 */
+	public static final int CONNECTIONS_HALIGN_CENTER_START = 1 << 17;
+	/**
+	 * "Horizontal" alignment constant. Labels should be centered between the
+	 * last two points on the connection. For connections with only two points,
+	 * this will behave the same as CENTER.
+	 */
+	public static final int CONNECTIONS_HALIGN_CENTER_END = 1 << 18;
+	/**
+	 * Style constant to indicate that connections between nodes should be curved
+	 * by default. A connection cannot by styled with any of CONNECTIONS_CURVED,
+	 * CONNECTIONS_STRAIGHT, or CONNECTIONS_BEZIER at the same time.
+	 */
+	//@tag style(arcs)
+	public static final int CONNECTIONS_CURVED = 1 << 1;
+	
+	/**
+	 * Style constant to indicate that connections between nodes should be straight by
+	 * default.  A connection cannot by styled with any of CONNECTIONS_CURVED,
+	 * CONNECTIONS_STRAIGHT, or CONNECTIONS_BEZIER at the same time.
+	 */
+	//@tag style(arcs)
+	public static final int CONNECTIONS_STRAIGHT = 1 << 0;
+	
+	/**
+	 * Style constant to indicate that connections should be drawn with solid 
+	 * lines (this is the default).
+	 */
+//	@tag style(arcs)
+	public static final int CONNECTIONS_SOLID = 1 << 6;
+	
+	/**
+	 * Style constant to indicate that connections should be drawn with dashed
+	 * lines.
+	 */
+//	@tag style(arcs)
+	public static final int CONNECTIONS_DASH = 1 << 7;
+	
+	/**
+	 * Style constant to indicate that connections should be drawn with
+	 * dotted lines.
+	 */
+//	@tag style(arcs)
+	public static final int CONNECTIONS_DOT = 1 << 8;
+	
+	/**
+	 * Style constant to indicate that connections should be drawn with
+	 * dash-dotted lines.
+	 */
+//	@tag style(arcs)
+	public static final int CONNECTIONS_DASH_DOT = 1 << 9;
+	
+	/**
+	 * Style constant to indicate that connections between nodes should be bezier-S
+	 * shaped. A connection cannot by styled with any of CONNECTIONS_CURVED,
+	 * CONNECTIONS_STRAIGHT, or CONNECTIONS_BEZIER at the same time.
+	 * 
+	 * Bezier curves are defined by a set of four points: two point in the layout
+	 * (start and end), and two related control points (also start and end). The
+	 * control points are defined relative to their corresponding layout point.
+	 * This definition includes an angle between the layout point and the line
+	 * between the two layout points, as well as a ratio distance from the corresponding
+	 * layout point. The ratio distance is defined as a fraction between 0 and 1
+	 * of the distance between the two layout points. Using this definition
+	 * allows bezier curves to have a consistant look regardless of the actual
+	 * positions of the nodes in the layouts.
+	 * 
+	 * @see IConnectionStyleBezierExtension
+	 * @see IConnectionEntityStyleBezierExtension
+	 */
+	//@tag style(arcs)
+	public static final int CONNECTIONS_BEZIER = 1 << 2;
+	
+	/**
+	 * Style constant to indicate that the Tree Graph Viewer should be 
+	 * compressed.
+	 * @tag style(tree_graph)
+	 */
+	public static final int TREE_GRAPH_COMPRESS = 1 << 0;
+	
+	
+	/**
+	 * Style constant to indicate that  the Tree Graph Viewer should use
+	 * a default "hanging" layout instead of the bushy "Normal" tree layout.
+	 * @tag style(tree_graph)
+	 */
+	public static final int TREE_GRAPH_HANGING_LAYOUT = 1 << 1;
+	
+	/**
+	 * Bitwise ANDs the styleToCheck integer with the given style.  
+	 * @param style
+	 * @param styleToCheck
+	 * @return boolean if styleToCheck is part of the style
+	 */
+	public static boolean checkStyle(int style, int styleToCheck) {
+		return ((style & styleToCheck) == styleToCheck);
+	}
+	
+	/**
+	 * Validates the given style for connections to see if it is legal. Returns
+	 * false if not.
+	 * @param style the style to check.
+	 * @return true iff the given style is legal.
+	 */
+	public static boolean validateConnectionStyle(int styleToValidate) {
+		int style = styleToValidate;
+		int illegal = CONNECTIONS_CURVED | CONNECTIONS_STRAIGHT | CONNECTIONS_BEZIER;
+		style &= illegal;
+		int rightBit = style & (-style);
+		boolean okay = (style == rightBit);
+		if (!okay) return okay;
+		
+		illegal = CONNECTIONS_DASH_DOT | CONNECTIONS_DASH | CONNECTIONS_DOT | CONNECTIONS_SOLID;
+		style = styleToValidate;
+		style &=illegal;
+		rightBit = style & (-style);
+		okay = (style == rightBit);
+		if (!okay) return okay;
+		
+		//@tag zest.bug.160368-ConnectionAlign.fix : must check the connections to make sure that there isnt' an illegal combination of alignments. 
+		illegal = CONNECTIONS_VALIGN_BOTTOM | CONNECTIONS_VALIGN_MIDDLE | CONNECTIONS_VALIGN_TOP;
+		style = styleToValidate;
+		style &=illegal;
+		rightBit = style & (-style);
+		return (style == rightBit);
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/AligningBendpointLocator.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/AligningBendpointLocator.java
new file mode 100644
index 0000000..2da18f3
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/AligningBendpointLocator.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.draw2d.AbstractLocator;
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+
+/**
+ * A locator that finds the middle of a connection based on the bendpoints.
+ * @author Del Myers
+ *
+ */
+//@tag zest(bug(154391-ArcEnds(fix))) : use this locator to ensure that labels will be in the middle of connections.
+//@tag zest.bug.160368-ConnectionAlign : replaces MidBenpointLocator in order to have finer control over alignment.
+public class AligningBendpointLocator extends AbstractLocator {
+	/**
+	 * "Vertical" alignment contstant. Figures should be placed in the middle
+	 * of the line.
+	 */
+	public static final int MIDDLE = 0;
+	/**
+	 * "Vertical" alignment constant. Figures should be placed above the line.
+	 */
+	public static final int ABOVE = 1;
+	/**
+	 * "Vertical" alignment constant. Figures should be placed below the line.
+	 */
+	public static final int BELOW = 2;
+	
+	/**
+	 * "Horizontal" alignment constant. Figures should be placed in the center
+	 * of the points on the line.
+	 */
+	public static final int CENTER = 0;
+	
+	/**
+	 * "Horizontal" alignment constant. Figures should be placed at the beginning
+	 * of the line. Figures will be anchored so that they have one end at the
+	 * beginning of the connection, not so that they are centered at the start
+	 * point. Which end of the figure is placed at that point will depend
+	 * on the direction of the first two points.
+	 */
+	public static final int BEGINNING = 1;
+	
+	/**
+	 * "Horizontal" alignment constant. Figures should be placed at the end of
+	 * the line. Figures will be anchored so that they have one end at the
+	 * beginning of the connection, not so that they are centered at the end
+	 * point. Which end of the figure is placed at that point will depend
+	 * on the direction of the last two points.
+	 */
+	public static final int END = 2;
+	
+	/**
+	 * "Horizontal" alignment constant. Figures should be centered between the
+	 * first two points on the connection. For connections with only two points, 
+	 * this will behave the same as CENTER.
+	 */
+	public static final int CENTER_BEGINNING = 3;
+	
+	/**
+	 * "Horizontal" alignment constant. Figures should be centered between the
+	 * last two points on the connection. For connections with only two points,
+	 * this will behave the same as CENTER.
+	 */
+	public static final int CENTER_END = 4;
+	private int horizontal;
+	private int vertical;
+	private Connection connection;
+	/**
+	 * @param connection
+	 */
+	public AligningBendpointLocator(Connection connection) {
+		this(connection, CENTER, MIDDLE);
+	}
+	
+	public AligningBendpointLocator(Connection connection, int horizontal, int vertical) {
+		this.connection = connection;
+		this.horizontal = horizontal;
+		this.vertical = vertical;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.ConnectionLocator#getReferencePoint()
+	 */
+	protected Point getReferencePoint() {
+		PointList points = getConnection().getPoints();
+		Point p = points.getMidpoint().getCopy();
+		PointList tempPoints = new PointList();
+		switch (horizontal) {
+		case BEGINNING:
+			p = points.getFirstPoint().getCopy();
+			break;
+		case END:
+			p = points.getLastPoint().getCopy();
+			break;
+		case CENTER_BEGINNING:
+			tempPoints.addPoint(points.getFirstPoint().getCopy());
+			tempPoints.addPoint(points.getPoint(1).getCopy());
+			p = tempPoints.getMidpoint().getCopy();
+			break;
+		case CENTER_END:
+			tempPoints = new PointList();
+			int s = points.size();
+			tempPoints.addPoint(points.getLastPoint().getCopy());
+			tempPoints.addPoint(points.getPoint(s-2).getCopy());
+			p = tempPoints.getMidpoint().getCopy();
+		case CENTER:
+		default:
+			p = points.getMidpoint().getCopy();
+		}
+		return p;
+	}
+	/**
+	 * Recalculates the position of the figure and returns the updated bounds.
+	 * @param target The figure to relocate
+	 */
+	public void relocate(IFigure target) {
+		Dimension prefSize = target.getPreferredSize();
+		Point center = getReferencePoint();
+		calculatePosition();
+		//@tag zest(bug(GEFProblem)) : there seems to be a bug in GEF that if the following is done, then labels get printed in the wrong location
+		//target.translateToRelative(center);
+		target.setBounds(getNewBounds(prefSize, center));
+	}
+	
+	/**
+	 * Translates the center point depending on the horizontal and veritical
+	 * alignments based on the given bounds.
+	 * @param center
+	 */
+	private void calculatePosition() {
+		PointList points = getConnection().getPoints();
+		int position = 0;
+		switch(horizontal) {
+		case BEGINNING:
+			Point first = points.getFirstPoint();
+			Point next = points.getPoint(1);
+			if (first.x <= next.x) 
+				position |= PositionConstants.EAST;
+			else
+				position |= PositionConstants.WEST;
+			break;
+		case END:
+			Point last = points.getLastPoint();
+			int s = points.size();
+			Point before = points.getPoint(s-1);
+			if (last.x <= before.x) 
+				position |= PositionConstants.EAST;
+			else
+				position |= PositionConstants.WEST;
+			break;
+		}
+		if (position == 0) position = PositionConstants.CENTER;
+		switch (vertical) {
+		case ABOVE:
+			position |= PositionConstants.NORTH;
+			break;
+		case BELOW:
+			position |= PositionConstants.SOUTH;
+			break;
+		case MIDDLE:
+			position |= PositionConstants.MIDDLE;
+		}
+		setRelativePosition(position);
+		
+	}
+
+	/**
+	 * @return the horizontal alignment.
+	 */
+	public int getHorizontalAlignment() {
+		return horizontal;
+	}
+	
+	/**
+	 * @param horizontal the horizontal alignment to set. One of CENTER,
+	 * BEGINNING, END, CENTER_BEGINNING, or CENTER_END.
+	 */
+	public void setHorizontalAlignment(int horizontal) {
+		this.horizontal = horizontal;
+	}
+	
+	/**
+	 * @param vertical the vertical alignment to set. One of ABOVE, MIDDLE, or
+	 * BELOW.
+	 */
+	public void setVerticalAlginment(int vertical) {
+		this.vertical = vertical;
+	}
+	
+	/**
+	 * @return the vertical alginment.
+	 */
+	public int getVerticalAlignment() {
+		return vertical;
+	}
+	
+	/**
+	 * @return the connection
+	 */
+	public Connection getConnection() {
+		return connection;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/Arc.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/Arc.java
new file mode 100644
index 0000000..9f65eb1
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/Arc.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Shape;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+/**
+ * A shape representation of an arc, so that arcs can be used in editparts.
+ * @tag bug(114452)
+ * @author Del Myers
+ */
+public class Arc extends Shape {
+	private int offset;
+	private int length;
+	 /**
+     * The closure type for an arc closed by drawing straight line
+     * segments from the start of the arc segment to the center
+     * of the full ellipse and from that point to the end of the arc segment.
+     */
+    public final static int PIE = 2;
+    /** 
+     * There are times when the clipping bounds and the bounds of the arc will be different
+     * allow for this.
+     */
+    private Rectangle arcBounds;
+	
+	public Arc() {
+		super();
+		setBounds(new Rectangle(0,0,0,0));
+		arcBounds = new Rectangle(0,0,0,0);
+	}
+	
+	
+	public Arc(Rectangle r, int offset, int length) {
+		super();
+		setBounds(r);
+		arcBounds = new Rectangle(r);
+		this.offset = offset;
+		this.length = length;
+	}
+	
+	public Arc(int x, int y, int width, int height, int offset, int length) {
+		this (new Rectangle(x, y, width, height), offset, length);
+	}
+	
+	
+	protected void fillShape(Graphics graphics) {
+		//graphics.setBackgroundColor(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_BLUE));
+		graphics.fillArc(getArcBounds(), offset, length);
+		/*for (int i = 0; i < 1000; i++) {
+			int x = (int)(Math.random()*getBounds().width+getBounds().x);
+			int y = (int)(Math.random()*getBounds().height+getBounds().x);
+			if (containsPoint(x,y)) {
+				graphics.drawPoint(x, y);
+			}
+		}*/
+	}
+
+	protected void outlineShape(Graphics graphics) {
+		graphics.drawArc(getArcBounds(), offset, length);
+	}
+	
+	public int getOffset() {
+		return offset;
+	}
+	
+	
+	public void setOffset(int offset) {
+		this.offset = offset;
+	}
+	
+	public int getLength() {
+		return length;
+	}
+	
+	public void setLength(int length) {
+		this.length = length;
+	}
+	
+	//@tag taken : from java.awt.geom.Arc2D
+	public boolean containsPoint(int x, int y) {
+		// Normalize the coordinates compared to the ellipse
+		// having a center at 0,0 and a radius of 0.5.
+		Rectangle r = getArcBounds();
+		double ellw = r.width;
+		if (ellw <= 0.0) {
+			return false;
+		}
+		double normx = (x - r.x) / ellw - 0.5;
+		double ellh = r.height;
+		if (ellh <= 0.0) {
+			return false;
+		}
+		double normy = (y - r.y) / ellh - 0.5;
+		double distSq = (normx * normx + normy * normy);
+		if (distSq >= 0.25) {
+			return false;
+		}
+		double angExt = Math.abs(getLength());
+		if (angExt >= 360.0) {
+			return true;
+		}
+		boolean inarc = containsAngle(-Math.toDegrees(Math.atan2(normy,
+				normx)));
+		return inarc;
+
+		/*// CHORD and OPEN behave the same way
+		if (inarc) {
+			if (angExt >= 180.0) {
+				return true;
+			}
+			// point must be outside the "pie triangle"
+		} else {
+			if (angExt <= 180.0) {
+				return false;
+			}
+			// point must be inside the "pie triangle"
+		}
+		// The point is inside the pie triangle iff it is on the same
+		// side of the line connecting the ends of the arc as the center.
+		double angle = Math.toRadians(-getAngleStart());
+		double x1 = Math.cos(angle);
+		double y1 = Math.sin(angle);
+		angle += Math.toRadians(-getAngleExtent());
+		double x2 = Math.cos(angle);
+		double y2 = Math.sin(angle);
+		boolean inside = (Line2D.relativeCCW(x1, y1, x2, y2, 2*normx, 2*normy) *
+				Line2D.relativeCCW(x1, y1, x2, y2, 0, 0) >= 0);
+		return inarc ? !inside : inside;
+		*/
+	}
+	
+	public boolean containsAngle(double angle) {
+		double angExt = getLength();
+		boolean backwards = (angExt < 0.0);
+		if (backwards) {
+			angExt = -angExt;
+		}
+		if (angExt >= 360.0) {
+			return true;
+		}
+		angle = normalizeDegrees(angle) - normalizeDegrees(getOffset());
+		if (backwards) {
+			angle = -angle;
+		}
+		if (angle < 0.0) {
+			angle += 360.0;
+		}
+
+
+		return (angle >= 0.0) && (angle < angExt);
+	}
+	
+	/*
+	 * Normalizes the specified angle into the range -180 to 180.
+	 */
+	static double normalizeDegrees(double angle) {
+		if (angle > 180.0) {
+			if (angle <= (180.0 + 360.0)) {
+				angle = angle - 360.0;
+			} else {
+				angle = Math.IEEEremainder(angle, 360.0);
+				// IEEEremainder can return -180 here for some input values...
+				if (angle == -180.0) {
+					angle = 180.0;
+				}
+			}
+		} else if (angle <= -180.0) {
+			if (angle > (-180.0 - 360.0)) {
+				angle = angle + 360.0;
+			} else {
+				angle = Math.IEEEremainder(angle, 360.0);
+				// IEEEremainder can return -180 here for some input values...
+				if (angle == -180.0) {
+					angle = 180.0;
+				}
+			}
+		}
+		return angle;
+	}
+	
+	public Rectangle getArcBounds() {
+		return arcBounds;
+	}
+	
+	protected void setArcBounds(Rectangle bounds) {
+		this.arcBounds = bounds;
+	}
+
+}
+
+
+
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ArcConnection.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ArcConnection.java
new file mode 100644
index 0000000..80e6c25
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ArcConnection.java
@@ -0,0 +1,609 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.draw2d.AbstractRouter;
+import org.eclipse.draw2d.AnchorListener;
+import org.eclipse.draw2d.ArrowLocator;
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.ConnectionAnchor;
+import org.eclipse.draw2d.ConnectionLocator;
+import org.eclipse.draw2d.ConnectionRouter;
+import org.eclipse.draw2d.DelegatingLayout;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.RotatableDecoration;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+
+/**
+ * 
+ * @author Del Myers
+ * 
+ * A connection between two anchor points. This connection is drawn as an arc,
+ * defined as the circular arc with the chord (ax, ay) - (bx, by) (where a and b
+ * are the anchors) and a depth d defined as the maximum distance from any point on
+ * the chord (i.e. a vector normal to the chord with magnitude d).
+ * 
+ * @tag bug(114452)
+ */
+public class ArcConnection extends Arc implements Connection, AnchorListener {
+
+	/**
+	 * Routes Connections directly from the source anchor to the target anchor with no
+	 * bendpoints in between.
+	 */
+	static class NullConnectionRouter
+		extends AbstractRouter
+	{
+		
+		/**
+		 * Constructs a new NullConnectionRouter.
+		 */
+		NullConnectionRouter() { }
+
+		/**
+		 * Routes the given Connection directly between the source and target anchors.
+		 * @param conn the connection to be routed
+		 */
+		public void route(Connection conn) {
+			PointList points = conn.getPoints();
+			points.removeAllPoints();
+			Point p;
+			p = getStartPoint(conn);
+			conn.translateToRelative(p = getStartPoint(conn));
+			points.addPoint(p);
+			p = getEndPoint(conn);
+			conn.translateToRelative(p = getEndPoint(conn));
+			points.addPoint(p);
+			conn.setPoints(points);
+		}
+
+	}
+	
+	/** The depth of the arc */
+	private int depth;
+	
+	//just for reference purposes: a point on the radius of the arc, halfway
+	//between the endpoints.
+	private double px;
+	private double py;
+	//decorations for the start and end of the arc.
+	private RotatableDecoration endArrow;
+	private RotatableDecoration startArrow;
+	
+	//list of points in the arc. This will include just the end points.
+	private PointList pointList;
+	
+	//method for routing connections.
+	private ConnectionRouter connectionRouter;
+	
+	//source and destination anchors.
+	private ConnectionAnchor source;
+	private ConnectionAnchor dest;
+	
+	//default connection router.
+	private static ConnectionRouter NullConnectionRouter = new NullConnectionRouter();
+	
+	
+	public ArcConnection() {
+		super();
+		this.pointList = new PointList();
+		connectionRouter = NullConnectionRouter;
+		this.depth = 0;
+		pointList.addPoint(new Point(0,0));
+		pointList.addPoint(new Point(100,100));
+		setLayoutManager(new DelegatingLayout());
+	}
+	
+	public ConnectionRouter getConnectionRouter() {
+		return connectionRouter;
+	}
+	
+	/**
+	 * Hooks the source and target anchors.
+	 * @see Figure#addNotify()
+	 */
+	public void addNotify() {
+		super.addNotify();
+		hookSourceAnchor();
+		hookTargetAnchor();
+	}
+
+	/**
+	 * Returns the list of points in this arc. Note: the points can't be changed using
+	 * setPoints, nor by changing the PointList. The PointList is fixed within this connection.
+	 */
+	public final PointList getPoints() {
+		return pointList.getCopy();
+	}
+	
+	/**
+	 * Returns the bounds which holds all the points in this. Returns any 
+	 * previously existing bounds, else calculates by unioning all the children's
+	 * dimensions.
+	 * @return the bounds
+	 */
+	//@tag bug(154176-ConnectionClip(fix)) : add children to the bounds.
+	public Rectangle getBounds() {
+		if (bounds == null) {
+			super.getBounds();
+			for (int i = 0; i < getChildren().size(); i++) {
+				IFigure child = (IFigure)getChildren().get(i);
+				bounds.union(child.getBounds());
+			}
+		}
+		return bounds;
+	}
+
+	public Object getRoutingConstraint() {
+		if (this.connectionRouter != null)
+			return connectionRouter.getConstraint(this);
+		return null;
+	}
+
+	public ConnectionAnchor getSourceAnchor() {
+		return source;
+	}
+
+	public ConnectionAnchor getTargetAnchor() {
+		return dest;
+	}
+
+	public void setConnectionRouter(ConnectionRouter router) {
+		if (this.connectionRouter == router) return;
+		ConnectionRouter oldRouter = connectionRouter;
+		if (router == null) router = NullConnectionRouter;
+		this.connectionRouter = router;
+		firePropertyChange(Connection.PROPERTY_CONNECTION_ROUTER, oldRouter, this.connectionRouter);
+	}
+
+	
+	
+	/**
+	 * Updates the arc for when point or depth changes occur.
+	 */
+	protected void updateArc(Point src, Point dest, int depth) {
+		double workingDepth = depth;
+		this.depth = depth;
+		//get cartesian coordinates: they are easier to work with.
+		//cartesian coordinates are easier to use for translations.
+		double x1 = src.x;
+		double y1 = -src.y;
+		double x2 = dest.x;
+		double y2 = -dest.y;
+		//	the center of the chord
+		double cartChordX = (x2 + x1)/2;
+		double cartChordY = (y2 + y1)/2;
+		
+		//special cases
+		if (depth == 0) {
+			doStraightLine(src, dest);
+			return;
+		} else if (src.equals(dest)) {
+			doCircle(src);
+			return;
+		}
+		
+		
+		if (x1 >= x2) {
+			workingDepth = -workingDepth;
+		}
+		
+		double chordLength = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
+		if (Math.abs(workingDepth) >= chordLength/2) {
+			workingDepth = (chordLength/3)*(workingDepth/Math.abs(workingDepth));
+		}
+		double r = (((chordLength/2)*(chordLength/2)) + ((double)workingDepth*workingDepth))/((double)2*workingDepth);
+		
+		//assume that the chord is perpendicular to the origin
+		//to find the angle of the chord.
+		double cartCenterX = 0;
+		double cartCenterY = 0;
+		
+		//Find a vector normal to the chord. This will be used for translating the
+		//circle back to screen coordinates.
+		double chordNormal = 0;
+
+		if (Math.abs(x1 - x2) <= .001) {
+			//slope of 0. NaN is easier to detect than 0.
+			chordNormal = Double.NaN;
+		} else if (Math.abs(y1-y2) <= 0.001) {
+			//infinite slope.
+			chordNormal = Double.POSITIVE_INFINITY;
+		} else {
+			chordNormal = -(double)(y2 - y1)/(x2 - x1);
+		}
+		
+		double th1;
+		if (Double.isNaN(chordNormal)) {
+			cartCenterX = (y1 > y2) ? (cartChordX-r+(workingDepth)) : (cartChordX+r-(workingDepth));
+			cartCenterY = cartChordY;
+			this.px = cartChordX + ((y1 > y2) ? (workingDepth) : (-workingDepth));
+			this.py = (-cartChordY);
+			th1 = Math.PI/2;
+		} else if (Double.isInfinite(chordNormal)) {
+			cartCenterX = cartChordX;
+			cartCenterY = cartChordY+r-(workingDepth);
+			this.px = cartChordX;
+			this.py = (-cartChordY)+workingDepth;
+			th1 = 0.0;
+		} else {
+			//assume that the center of the chord is on the origin.
+			th1 = Math.atan(chordNormal);
+			cartCenterX = (r-(double)(workingDepth))*Math.sin(th1)+cartChordX;//cartChordX+r -depth;
+			cartCenterY = (r-(double)(workingDepth))*Math.cos(th1)+cartChordY;//cartChordY+r-depth;
+			this.px = (-workingDepth)*Math.sin(th1)+cartChordX;
+			this.py = -((-workingDepth)*Math.cos(th1)+cartChordY);
+		}
+		
+		//update the points and depth
+		pointList.removeAllPoints();
+		pointList.addPoint(src);
+		pointList.addPoint(new Point(Math.round(px), Math.round(py)));
+		pointList.addPoint(dest);
+		
+		//figure out the new angles
+		//translate the points to the center of the circle
+		double cartArcX1 = x1 - cartCenterX;
+		double cartArcY1 = y1 - cartCenterY;
+		double cartArcX2 = x2 - cartCenterX;
+		double cartArcY2 = y2 - cartCenterY;
+		
+		double arcStart = angle360(cartArcX1, cartArcY1);
+		double arcEnd = angle360(cartArcX2, cartArcY2);
+		if (arcEnd < arcStart) {
+			arcEnd = arcEnd + 360;
+		}
+		double  arcLength = arcEnd-arcStart;//findAngleDegrees(arcStart, arcEnd);
+		int padding = (chordLength > 100) ? 4 : 0;
+		if (depth < 0) padding = -padding; 
+		setOffset((int)(Math.round(arcStart - padding)));
+		setLength((int)(Math.round(arcLength+padding*(chordLength/100))));
+		
+		//update the bounds
+		double br = Math.abs(r);
+		double topx = cartCenterX - br;
+		double topy = cartCenterY + br;
+		double width = br*2;
+			
+		Rectangle b = new Rectangle((int)x1, -(int)y1, (int)(px-x1), (int)(py+y1));
+		if (b.width < 0) {
+			b.width = -b.width;
+			b.x = b.x - b.width;
+		}
+		if (b.height < 0){
+			b.height = -b.height;
+			b.y = b.y-b.height;
+		}
+		Rectangle b2 = new Rectangle((int)x2, (int)-y2, (int)(px-x2), (int)(py+y2));
+		if (b2.width < 0) {
+			b2.width = -b2.width;
+			b2.x = b2.x - b2.width;
+		}
+		if (b2.height < 0){
+			b2.height = -b2.height;
+			b2.y = b2.y-b2.height;
+		}
+		int b3x = Math.min(b2.x, b.x);
+		int b3y = Math.min(b.y, b2.y);
+		arcEnd = arcEnd % 360;
+		int boundsTop = b3y;
+		int boundsLeft = b3x;
+		int boundsBottom = boundsTop + (b.height+b2.height);
+		int boundsRight = boundsLeft + (b.width+b2.width);
+		if (arcEnd >= 90 && (arcEnd-arcLength) <= 90) {
+			boundsTop = -(int)topy;
+		}
+		if (arcEnd >= 180 && (arcEnd - arcLength) <= 180) {
+			boundsLeft = (int)topx;
+		}
+		if ((arcEnd >= 270 && (arcEnd -arcLength) <= 270) || (arcEnd-arcLength+360 <= 270)) {
+			boundsBottom = (int)(width-topy);
+		}
+		if (arcEnd >=0 && (arcEnd-arcLength) <= 0){
+			boundsRight = (int)(topx + width);
+		}
+		Rectangle b3 = new Rectangle(boundsLeft-5, boundsTop-5, boundsRight-boundsLeft+10, boundsBottom-boundsTop+10);
+		setBounds(b3);
+		setArcBounds(new Rectangle((int)topx, -(int)topy, (int)width, (int)width));
+		
+		
+		//this.bounds = null;
+		
+	}
+	
+	//source and destination are the same. create a circle that passes through the point.
+	
+	private void doCircle(Point src) {
+		setOffset(0);
+		setLength(360);
+		Rectangle circleBounds = new Rectangle(src.x - depth/2, src.y - depth, depth, depth);
+		setArcBounds(circleBounds);
+		setBounds(circleBounds);
+		pointList.removeAllPoints();
+		pointList.addPoint(src.getCopy());
+		pointList.addPoint(new Point(src.x, src.y-depth));
+		pointList.addPoint(src.getCopy());
+	}
+
+	private void doStraightLine(Point src, Point dest) {
+		int x1 = src.x;
+		int y1 = src.y;
+		int x2 = dest.x;
+		int y2 = dest.y;
+		//just a straight line.
+		if (x1 > x2) {
+			int t = x2;
+			x2 = x1;
+			x1 = t;
+		}
+		if (y1 > y2) {
+			int t = y2;
+			y2 = y1;
+			y1 = t;
+		}
+		Rectangle bounds = new Rectangle((int)x1-2, (int)y1-2, (int)(x2-x1)+4, (int)(y2-y1)+4);
+		setBounds(bounds);
+		setArcBounds(bounds);
+		
+		pointList.removeAllPoints();
+		pointList.addPoint(src.getCopy());
+		pointList.addPoint(new Point((x1+x2)/2, (y1+y2)/2));
+		pointList.addPoint(dest.getCopy());
+		
+	}
+
+	/**
+	 * This implementation only pays attention to the first and the last points in the
+	 * list because Arcs don't allow for bendpoints. The new point list will consist of
+	 * the two end-points and a point that describes the depth of the arc.
+	 */
+	public final void setPoints(PointList list) {
+		Point src = list.getFirstPoint();
+		Point dest = list.getLastPoint();
+		//create the new arc.
+		updateArc(src, dest, getDepth());
+		
+		firePropertyChange(Connection.PROPERTY_POINTS, null, pointList);
+		repaint();
+		
+	}
+	
+	public int getDepth() {
+		return depth;
+	}
+	
+	/**
+	 * Sets the depth of the arc. This is defined as the maximum distance from the
+	 * line that connects the source and target of this connection. The sign of the
+	 * depth (+ve or -ve) will define which side of the line the arc will appear on.
+	 * @param depth the depth of the arc.
+	 */
+	public void setDepth(int depth) {
+		updateArc(getPoints().getFirstPoint(), getPoints().getLastPoint(), depth);
+		repaint();
+	}
+	
+	/**
+	 * Takes the polar coordinates x1, y1 and returns their angle between 0 and 360 degrees.
+	 * @param x1 polar coordinate.
+	 * @param y1 polar coordinate
+	 * @return polar angle in 360 degrees.
+	 */
+	protected double angle360(double x1, double y1) {
+		double theta = Math.toDegrees(Math.atan(y1/x1));
+		switch (findQuadrant(x1,y1)) {
+			case 1: return theta;
+			case 2: 
+			case 3: return theta+180; 
+			case 4: return theta+360;
+			default: return theta;
+		}
+	}
+	
+	
+	/**
+	 * 
+	 * finds the shortest angle between the two given angles. Assumes that the angles
+	 * are between 0-360 degrees.
+	 *
+	 */
+	protected double findAngleDegrees(double a1, double a2) {
+		double diff = a2-a1;
+		double diff2 = diff-360;
+		if (diff < 0) {
+			diff2 = 360+diff;
+		}
+		if (Math.abs(diff) < Math.abs(diff2)) {
+			return diff;
+		}
+		return diff2;
+	}
+	
+	
+	//find the quadrant, assume points are centered at 0,0
+	protected int findQuadrant (double x, double y) {
+		if (y > 0) {
+			if (x > 0) {
+				return 1;
+			} else {
+				return 2;
+			}
+		} else {
+			if (x > 0) {
+				return 4;
+			} else {
+				return 3;
+			}
+		}
+	}
+
+	
+	public void setRoutingConstraint(Object cons) {
+		if (this.connectionRouter != null) connectionRouter.setConstraint(this, cons);
+	}
+
+	public void setSourceAnchor(ConnectionAnchor anchor) {
+		if (anchor == this.source) return;
+		unhookSourceAnchor();
+		this.source = anchor;
+		if (getParent()!=null) hookSourceAnchor();
+		revalidate();
+	}
+
+	public void setTargetAnchor(ConnectionAnchor anchor) {
+		if (anchor == this.dest) return;
+		unhookTargetAnchor();
+		this.dest = anchor;
+		if (getParent()!=null) hookTargetAnchor();
+		revalidate();
+	}
+	
+	private void unhookSourceAnchor() {
+		if (getSourceAnchor() != null)
+			getSourceAnchor().removeAnchorListener(this);
+	}
+
+	private void unhookTargetAnchor() {
+		if (getTargetAnchor() != null)
+			getTargetAnchor().removeAnchorListener(this);
+	}
+	
+	public void revalidate() {
+		super.revalidate();
+		if (connectionRouter != null)
+			connectionRouter.invalidate(this);
+	}
+	
+	
+	protected final void fillShape(Graphics graphics) {
+		
+	}
+	
+	protected void outlineShape(Graphics graphics) {
+		Color c = graphics.getForegroundColor();
+		graphics.setForegroundColor(c.getDevice().getSystemColor(SWT.COLOR_GRAY));
+		//graphics.drawOval(getBounds());
+		graphics.setForegroundColor(c);
+		Point source =getPoints().getFirstPoint();
+		Point target = getPoints().getLastPoint();
+		Rectangle bounds = getBounds();
+		if (depth == 0) {
+			graphics.drawLine(source, target);
+			return;
+		}
+		graphics.setClip(new Rectangle(bounds.x-1, bounds.y-1, bounds.width+2, bounds.height+2));
+		super.outlineShape(graphics);
+	}
+	
+	/*public boolean containsPoint(int x, int y) {
+		if (depth == 0) {
+			//calculate for a straight line.
+			Point source = getPoints().getFirstPoint();
+			Point target = getPoints().getLastPoint();
+			double m = ((double)target.y - (double)source.y)/((double)target.x-(double)source.x);
+			double dy = m*(source.x-x) + y;
+			return (Math.abs(dy) <= .01);
+		}
+		if (!super.containsPoint(x, y))
+			return false;
+		
+		Rectangle r = getArcBounds();
+		double ellw = r.width;
+		double normx = (x - r.x) / ellw - 0.5;
+		double ellh = r.height;
+		double normy = (y - r.y) / ellh - 0.5;
+		double distSq = (normx * normx + normy * normy);
+		return (Math.abs(1-distSq) <= .001);
+		
+	}*/
+	
+	public boolean containsPoint(int x, int y) {
+		return false;
+	}
+
+	private void hookSourceAnchor() {
+		if (getSourceAnchor() != null)
+			getSourceAnchor().addAnchorListener(this);
+	}
+
+	private void hookTargetAnchor() {
+		if (getTargetAnchor() != null)
+			getTargetAnchor().addAnchorListener(this);
+	}
+	
+
+	public void anchorMoved(ConnectionAnchor anchor) {
+		revalidate();
+	}
+	
+	/**
+	 * Layouts this polyline. If the start and end anchors are present, the connection router 
+	 * is used to route this, after which it is laid out. It also fires a moved method.
+	 */
+	public void layout() {
+		if (getSourceAnchor() != null && getTargetAnchor() != null)
+			connectionRouter.route(this);
+		Rectangle oldBounds = bounds;
+		super.layout();
+		
+		if (!getBounds().contains(oldBounds)) {
+			getParent().translateToParent(oldBounds);
+			getUpdateManager().addDirtyRegion(getParent(), oldBounds);
+		}
+		
+		repaint();
+		fireFigureMoved();
+	}
+	
+	/**
+	 * Sets the decoration to be used at the end of the {@link Connection}.
+	 * @param dec the new target decoration
+	 */
+	public void setTargetDecoration(RotatableDecoration dec) {
+		if (endArrow == dec)
+			return;
+		if (endArrow != null)
+			remove(endArrow);
+		endArrow = dec;
+		if (endArrow != null) {
+			if (depth != 0)
+				add(endArrow, new ArcLocator(this, ConnectionLocator.TARGET));
+			else 
+				add(endArrow, new ArrowLocator(this,ConnectionLocator.TARGET));
+		}
+	}
+	
+	/**
+	 * Sets the decoration to be used at the start of the {@link Connection}.
+	 * @param dec the new source decoration
+	 * @since 2.0
+	 */
+	public void setSourceDecoration(RotatableDecoration dec) {
+		if (startArrow == dec)
+			return;
+		if (startArrow != null)
+			remove(startArrow);
+		startArrow = dec;
+		if (startArrow != null) {
+			if (depth != 0)
+				add(startArrow, new ArcLocator(this, ConnectionLocator.SOURCE));
+			else 
+				add(startArrow, new ArrowLocator(this,ConnectionLocator.SOURCE));
+		}
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ArcLocator.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ArcLocator.java
new file mode 100644
index 0000000..83371ae
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ArcLocator.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.ConnectionLocator;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.RotatableDecoration;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+/**
+ * A locator for arcs, so that child figures can properly position themselves on arcs.
+ * @tag bug(114452)
+ * @author Del Myers
+ */
+class ArcLocator extends ConnectionLocator {
+	
+	
+	public ArcLocator(Connection connection, int location) {
+		super(connection, location);
+	}
+	
+	
+	public void relocate(IFigure target) {
+		if (!(target instanceof RotatableDecoration)) return;
+		if (!(getConnection() instanceof ArcConnection)) return;
+		Point alignmentPoint = getAlignementPoint();
+		((RotatableDecoration)target).setLocation(alignmentPoint);
+		rotate((RotatableDecoration)target);
+	}
+	
+	protected int getQuadrant(Point p) {
+		ArcConnection conn = (ArcConnection) getConnection();
+		int centerx = conn.getArcBounds().x + conn.getArcBounds().width/2;
+		int centery = conn.getArcBounds().y + conn.getArcBounds().height/2;
+		if (p.y > centery) {
+			if (p.x > centerx) {
+				return 4;
+			} else {
+				return 3;
+			}
+		} else {
+			if (p.x < centerx) {
+				return 2;
+			} else {
+				return 1;
+			}
+		}
+	}
+	
+	protected Point getAlignementPoint() {
+		Point point = null;
+		ArcConnection connection = (ArcConnection)getConnection();
+		if (getAlignment() == SOURCE) {
+			point = connection.getPoints().getFirstPoint().getCopy();
+		} else if (getAlignment() == TARGET) {
+			point = connection.getPoints().getLastPoint().getCopy();
+		} else {
+			point = connection.getPoints().getMidpoint().getCopy();
+		}
+		return point;
+	}
+	protected void rotate(RotatableDecoration target) {
+		ArcConnection connection = (ArcConnection)getConnection();
+		Point point = getAlignementPoint();
+		Rectangle arcBounds = connection.getArcBounds();
+		//normalize the coordinates.
+		double bx = arcBounds.x;
+		double by = arcBounds.y;
+		double bw = arcBounds.width;
+		double bh = arcBounds.height;
+		
+		int q = getQuadrant(point);
+		Rectangle tbounds = target.getBounds();
+		//the new location of the arrow will depend on what quadrant it is in
+		switch (q) {
+			case 1: 
+				 point.x = point.x+tbounds.width;
+				 point.y = point.y+tbounds.height;
+				break;
+			case 2:
+				point.x = point.x+tbounds.width;
+				point.y = point.y-tbounds.height;
+				break;
+			case 3:
+				point.x = point.x-tbounds.width;
+				point.y = point.y-tbounds.height;
+				break;
+			case 4:
+				point.x = point.x-tbounds.width;
+				point.y = point.y+tbounds.height;
+				break;
+		}
+		
+		
+		double normx = (point.x - (bx + bw/2));
+		double normy = (point.y - (by+ bh/2));
+		double th = Math.atan(normy/normx);
+		//adjust theta according to quadrant
+		switch (q) {
+			case 4:
+				th = th + Math.PI;
+			case 2: 
+			case 3: 
+				th = th + Math.PI;
+				break;
+		}
+
+		//translate back from polar coordinates.
+		double nx = (bw/2)*Math.cos(th) + bx + bw/2;
+		double ny = (bh/2)*Math.sin(th) + by + bh/2;
+		target.setReferencePoint(new Point(Math.round(nx), Math.round(ny)));
+	}
+	
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/Bezier.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/Bezier.java
new file mode 100644
index 0000000..f67fba0
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/Bezier.java
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Polyline;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+/**
+ * Simple Bezier curve shape.
+ * @author Del Myers
+ *
+ */
+
+//@tag bug(152530-Bezier(fix)) : a basic shape for drawing bezier curves.
+public class Bezier extends Polyline {
+	//the control attached to the start point.
+	private Point startControl;
+	//the control attached to the end point.
+	private Point endControl;
+	private boolean isValid;
+	
+	
+	private static Object lock = new Object();
+	
+	
+	//	the number of line segments between the start and end points.
+	public static int SEGMENTS;
+	//@tag performance(optimization) : pre-compute the weights for faster updates of bezier curves. Greatly reduces the number of multiplications.
+	private static float[] WEIGHTS1;
+	private static float[] WEIGHTS2;
+	
+	//allow users to change the number of segments
+	static {
+		synchronized (lock) {
+			SEGMENTS = 58;
+			WEIGHTS1 = COMPUTE_WEIGHTS_1();
+			WEIGHTS2 = COMPUTE_WEIGHTS_2();
+		}
+	}
+	
+	public Bezier(Point start, Point end, Point startControl, Point endControl) {
+		super();
+		setStart(start);
+		setEnd(end);
+		this.startControl = startControl;
+		this.endControl = endControl;
+		this.isValid = false;
+
+	}
+	
+	
+	//set the number of segments to be used in drawing.
+	public static void setSegments(int numSegments) {
+		synchronized (lock) {
+			SEGMENTS = numSegments;
+			WEIGHTS1 = COMPUTE_WEIGHTS_1();
+			WEIGHTS2 = COMPUTE_WEIGHTS_2();
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Shape#fillShape(org.eclipse.draw2d.Graphics)
+	 */
+	protected void fillShape(Graphics graphics) {
+		reCompute();
+		super.fillShape(graphics);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Shape#outlineShape(org.eclipse.draw2d.Graphics)
+	 */
+	protected void outlineShape(Graphics graphics) {
+		reCompute();
+		graphics.setClip(new Rectangle(0,0,3000,3000));
+		graphics.drawPolyline(getPoints().toIntArray());
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Polyline#setStart(org.eclipse.draw2d.geometry.Point)
+	 */
+	public void setStart(Point start) {
+		super.setStart(start);
+		isValid = false;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Polyline#setEnd(org.eclipse.draw2d.geometry.Point)
+	 */
+	public void setEnd(Point end) {
+		super.setEnd(end);
+		isValid = false;
+	}
+	
+	/**
+	 * @param endControl the endControl to set
+	 */
+	public void setEndControl(Point endControl) {
+		this.endControl = endControl;
+		isValid = false;
+	}
+	
+	/**
+	 * @param startControl the startControl to set
+	 */
+	public void setStartControl(Point startControl) {
+		this.startControl = startControl;
+		isValid = false;
+	}
+	
+	/**
+	 * @return the startControl
+	 */
+	public Point getStartControl() {
+		return startControl;
+	}
+	
+	/**
+	 * @return the endControl
+	 */
+	public Point getEndControl() {
+		return endControl;
+	}
+	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#revalidate()
+	 */
+	public void revalidate() {
+		reCompute();
+		super.revalidate();
+	}
+	
+	public final void reCompute() {
+		if (isValid) return;
+		Point start = getStart();
+		Point end = getEnd();
+		PointList points = getPoints();
+		points.removeAllPoints();
+		points.addPoint(start);
+		float lengthSquared = (float)(end.x - start.x)*(end.x-start.x)+(start.y-end.y)*(start.y-end.y);
+		float segmentsSquared = SEGMENTS*SEGMENTS*64;
+		int step = 1;
+		//optimize the number of line segments to use. If it isn't going to look
+		//bad, use less.
+		if (lengthSquared < .0001 && lengthSquared > -.0001) {
+			//may as well be 0
+			step = SEGMENTS;
+		} else if (lengthSquared < segmentsSquared) {
+			step = (int)Math.round(((float)segmentsSquared)/lengthSquared);
+		}
+		//always have at least 8 line segments
+		if (step > SEGMENTS/8) step = SEGMENTS/8;
+		if (step <= 0) step = 1;
+		synchronized(lock) {
+			for (int i = step; i < SEGMENTS; i+=step) {
+				Point p = new Point(
+						Math.round(t0(i)*start.x + t1(i)*startControl.x + t2(i)*endControl.x+t3(i)*end.x),
+						Math.round(t0(i)*start.y + t1(i)*startControl.y + t2(i)*endControl.y+t3(i)*end.y)
+				);
+				points.addPoint(p);
+			}
+		}
+		points.addPoint(end);
+		super.setPoints(points);
+		isValid = true;
+	}
+	
+	private static final float[] COMPUTE_WEIGHTS_1() {
+		float[] weights = new float[SEGMENTS+1];
+		float t = 0;
+		weights[0] = 1;
+		weights[SEGMENTS] = 0;
+		for (int i = 1; i < SEGMENTS; i++) {
+			t = ((float)i)/((float)SEGMENTS);
+			float oneMinusT = (1-t);
+			weights[i] = oneMinusT*oneMinusT*oneMinusT;
+		}
+		return weights;
+	}
+	
+	private static final float[] COMPUTE_WEIGHTS_2() {
+		float[] weights = new float[SEGMENTS+1];
+		float t = 0;
+		weights[0] = 1;
+		weights[SEGMENTS] = 0;
+		for (int i = 1; i < SEGMENTS; i++) {
+			t = ((float)i)/((float)SEGMENTS);
+			float oneMinusT = (1-t);
+			weights[i] = t*oneMinusT*oneMinusT*3;
+		}
+		return weights;
+	}
+	
+	private static final float t0(int s) {
+		return WEIGHTS1[s];
+	}
+	
+	private static final float t1(int s) {
+		return WEIGHTS2[s];
+	}
+	
+	private static final float t2(int s) {
+		return WEIGHTS2[SEGMENTS-s];
+	}
+	
+	private static final float t3(int s) {
+		return WEIGHTS1[SEGMENTS-s];
+	}
+
+}
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/BezierConnection.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/BezierConnection.java
new file mode 100644
index 0000000..379bcc6
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/BezierConnection.java
@@ -0,0 +1,391 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.draw2d.AbstractRouter;
+import org.eclipse.draw2d.AnchorListener;
+import org.eclipse.draw2d.ArrowLocator;
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.ConnectionAnchor;
+import org.eclipse.draw2d.ConnectionLocator;
+import org.eclipse.draw2d.ConnectionRouter;
+import org.eclipse.draw2d.DelegatingLayout;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.RotatableDecoration;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+
+
+/**
+ * A connection that uses Bezier curves.
+ * 
+ * Bezier curves are defined by a set of four points: two point in the layout
+ * (start and end), and two related control points (also start and end). The
+ * control points are defined relative to their corresponding layout point.
+ * This definition includes an angle between the layout point and the line
+ * between the two layout points, as well as a ratio distance from the corresponding
+ * layout point. The ratio distance is defined as a fraction between 0 and 1
+ * of the distance between the two layout points. Using this definition
+ * allows bezier curves to have a consistant look regardless of the actual
+ * positions of the nodes in the layouts. 
+ * @author Del Myers
+ *
+ */
+//@tag zest(bug(152530-Bezier(fix)))
+public class BezierConnection extends Bezier implements Connection, AnchorListener {
+
+	private double startAngle;
+	private double startLength;
+	private double endAngle;
+	private double endLength;
+	private RotatableDecoration startArrow, endArrow;
+
+
+	/**
+	 * @param startAngle the angle from the line that the first control point is on.
+	 * @param startLength the distance from the start point that the first control point is  as a percentage of the distance between the endpoints.
+	 * @param endAngle the angle from the line that the second control point is on.
+	 * @param endLength the distance from the endpoint that the last control point is as a percentage of the distance between the endpoints.
+	 */
+	public BezierConnection(double startAngle, double startLength, double endAngle, double endLength) {
+		super(new Point(0,0), new Point(0,0), new Point(0,0), new Point(0,0));
+		this.startAngle = startAngle;
+		this.startLength = startLength;
+		this.endAngle = endAngle;
+		this.endLength = endLength;
+		setConnectionRouter(null);
+		setLayoutManager(new DelegatingLayout());
+		resetControls();
+	}
+
+	private static ConnectionRouter NullConnectionRouter = new NullConnectionRouter();
+	
+	/**
+	 * Routes Connections directly from the source anchor to the target anchor with no
+	 * bendpoints in between.
+	 */
+	static class NullConnectionRouter
+		extends AbstractRouter
+	{
+		
+		/**
+		 * Constructs a new NullConnectionRouter.
+		 */
+		NullConnectionRouter() { }
+
+		/**
+		 * Routes the given Connection directly between the source and target anchors.
+		 * @param conn the connection to be routed
+		 */
+		public void route(Connection conn) {
+			PointList points = conn.getPoints();
+			points.removeAllPoints();
+			Point p;
+			p = getStartPoint(conn);
+			conn.translateToRelative(p = getStartPoint(conn));
+			points.addPoint(p);
+			p = getEndPoint(conn);
+			conn.translateToRelative(p = getEndPoint(conn));
+			points.addPoint(p);
+			conn.setPoints(points);
+		}
+
+	}
+
+	private ConnectionRouter connectionRouter;
+	private ConnectionAnchor source;
+	private ConnectionAnchor dest;
+	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Connection#getConnectionRouter()
+	 */
+	public ConnectionRouter getConnectionRouter() {
+		return connectionRouter;
+	}
+
+	private void unhookSourceAnchor() {
+		if (getSourceAnchor() != null)
+			getSourceAnchor().removeAnchorListener(this);
+	}
+
+	private void unhookTargetAnchor() {
+		if (getTargetAnchor() != null)
+			getTargetAnchor().removeAnchorListener(this);
+	}
+	
+	private void hookSourceAnchor() {
+		if (getSourceAnchor() != null)
+			getSourceAnchor().addAnchorListener(this);
+	}
+
+	private void hookTargetAnchor() {
+		if (getTargetAnchor() != null)
+			getTargetAnchor().addAnchorListener(this);
+	}
+	
+	public void setRoutingConstraint(Object cons) {
+		if (this.connectionRouter != null) connectionRouter.setConstraint(this, cons);
+	}
+
+	public void setSourceAnchor(ConnectionAnchor anchor) {
+		if (anchor == this.source) return;
+		unhookSourceAnchor();
+		this.source = anchor;
+		if (getParent()!=null) hookSourceAnchor();
+		revalidate();
+	}
+	
+
+	
+	
+
+	public void setTargetAnchor(ConnectionAnchor anchor) {
+		if (anchor == this.dest) return;
+		unhookTargetAnchor();
+		this.dest = anchor;
+		if (getParent()!=null) hookTargetAnchor();
+		revalidate();
+	}
+	
+	
+	/**
+	 * Sets the decoration to be used at the start of the {@link Connection}.
+	 * @param dec the new source decoration
+	 * @since 2.0
+	 */
+	public void setSourceDecoration(RotatableDecoration dec) {
+		if (startArrow == dec)
+			return;
+		if (startArrow != null)
+			remove(startArrow);
+		startArrow = dec;
+		if (startArrow != null)
+			add(startArrow, new ArrowLocator(this, ConnectionLocator.SOURCE));
+	}
+	
+	/**
+	 * @return the source decoration (may be null)
+	 */
+	protected RotatableDecoration getSourceDecoration() {
+		return startArrow;
+	}
+	
+	/**
+	 * Sets the decoration to be used at the end of the {@link Connection}.
+	 * @param dec the new target decoration
+	 */
+	public void setTargetDecoration(RotatableDecoration dec) {
+		if (endArrow == dec)
+			return;
+		if (endArrow != null)
+			remove(endArrow);
+		endArrow = dec;
+		if (endArrow != null)
+			add(endArrow, new ArrowLocator(this, ConnectionLocator.TARGET));
+	}
+	
+	/**
+	 * @return the target decoration (may be null)
+	 * 
+	 * @since 2.0
+	 */
+	protected RotatableDecoration getTargetDecoration() {
+		return endArrow;
+	}
+
+	
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.AnchorListener#anchorMoved(org.eclipse.draw2d.ConnectionAnchor)
+	 */
+	public void anchorMoved(ConnectionAnchor anchor) {
+		revalidate();
+	}
+	
+	/**
+	 * Returns the list of points in this arc. Note: the points can't be changed using
+	 * setPoints, nor by changing the PointList. The PointList is fixed within this connection.
+	 */
+	public final PointList getPoints() {
+		return super.getPoints().getCopy();
+	}
+
+	public Object getRoutingConstraint() {
+		if (this.connectionRouter != null)
+			return connectionRouter.getConstraint(this);
+		return null;
+	}
+
+	public ConnectionAnchor getSourceAnchor() {
+		return source;
+	}
+
+	public ConnectionAnchor getTargetAnchor() {
+		return dest;
+	}
+	
+	
+
+	public void setConnectionRouter(ConnectionRouter router) {
+		if (router == null) router = NullConnectionRouter;
+		if (this.connectionRouter == router) return;
+		ConnectionRouter oldRouter = connectionRouter;
+		this.connectionRouter = router;
+		firePropertyChange(Connection.PROPERTY_CONNECTION_ROUTER, oldRouter, this.connectionRouter);
+	}
+	
+	public void revalidate() {
+		super.revalidate();
+		if (connectionRouter != null)
+			connectionRouter.invalidate(this);
+	}
+	
+	
+	/**
+	 * Returns the bounds which holds all the points in this polyline connection. Returns any 
+	 * previously existing bounds, else calculates by unioning all the children's
+	 * dimensions.
+	 * @return the bounds
+	 */
+//	@tag zest(bug(154176-ConnectionClip(fix))) : add children to the bounds.
+	public Rectangle getBounds() {
+		if (bounds == null) {
+			super.getBounds();
+			for (int i = 0; i < getChildren().size(); i++) {
+				IFigure child = (IFigure)getChildren().get(i);
+				bounds.union(child.getBounds());
+			}
+		}
+		return bounds;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Polyline#setPoints(org.eclipse.draw2d.geometry.PointList)
+	 */
+	public void setPoints(PointList points) {
+		setStart(points.getFirstPoint());
+		setEnd(points.getLastPoint());
+		resetControls();
+		repaint();
+	}
+
+	/**
+	 * @param firstPoint
+	 * @param lastPoint
+	 */
+	private void resetControls() {
+		Point firstPoint = getStart();
+		Point lastPoint = getEnd();
+		Point startControl;
+		Point endControl;
+		double distance = Math.sqrt((lastPoint.x-firstPoint.x)*(lastPoint.x-firstPoint.x)+(firstPoint.y-lastPoint.y)*(firstPoint.y-lastPoint.y));
+		double m = (firstPoint.y - lastPoint.y)/(double)(lastPoint.x - firstPoint.x);
+		double theta = Math.atan(m);
+		if (firstPoint.x > lastPoint.x) {theta = theta + Math.PI;}
+		double sar = (Math.toRadians(getStartAngle()) + theta);
+		double ear = (theta-Math.toRadians(getEndAngle()));
+		
+		double length = distance*getStartLength();
+		double controlX = length*Math.cos(sar);
+		double controlY = length*Math.sin(sar);
+		startControl = new Point(firstPoint.x + Math.round(controlX), firstPoint.y - Math.round(controlY));
+		
+		length = distance*getEndLength();
+		controlX =length*Math.cos(ear);
+		controlY = length*Math.sin(ear);
+		endControl = new Point(lastPoint.x - Math.round(controlX), lastPoint.y + Math.round(controlY));
+		
+		setStartControl(startControl);
+		setEndControl(endControl);
+		
+	}
+	
+	/**
+	 * @return the startLength
+	 */
+	public double getStartLength() {
+		return startLength;
+	}
+	
+	/**
+	 * @return the endLength
+	 */
+	public double getEndLength() {
+		return endLength;
+	}
+	
+	/**
+	 * @param startLength the startLength to set
+	 */
+	public void setStartLength(double startLength) {
+		this.startLength = startLength;
+	}
+	
+	/**
+	 * @param endLength the endLength to set
+	 */
+	public void setEndLength(double endLength) {
+		this.endLength = endLength;
+	}
+	
+	/**
+	 * @return the startAngle
+	 */
+	public double getStartAngle() {
+		return startAngle;
+	}
+	
+	/**
+	 * @return the endAngle
+	 */
+	public double getEndAngle() {
+		return endAngle;
+	}
+	
+	/**
+	 * @param startAngle the startAngle to set
+	 */
+	public void setStartAngle(int startAngle) {
+		this.startAngle = startAngle;
+		resetControls();
+	}
+	
+	/**
+	 * @param endAngle the endAngle to set
+	 */
+	public void setEndAngle(int endAngle) {
+		this.endAngle = endAngle;
+		resetControls();
+	}
+	
+	/**
+	 * Layouts this polyline. If the start and end anchors are present, the connection router 
+	 * is used to route this, after which it is laid out. It also fires a moved method.
+	 */
+	public void layout() {
+		if (getSourceAnchor() != null && getTargetAnchor() != null)
+			connectionRouter.route(this);
+		Rectangle oldBounds = bounds;
+		super.layout();
+		
+		if (!getBounds().contains(oldBounds)) {
+			getParent().translateToParent(oldBounds);
+			getUpdateManager().addDirtyRegion(getParent(), oldBounds);
+		}
+		
+		repaint();
+		fireFigureMoved();
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/CachedLabel.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/CachedLabel.java
new file mode 100644
index 0000000..667c116
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/CachedLabel.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.draw2d.Animation;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Label;
+import org.eclipse.draw2d.SWTGraphics;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.mylar.zest.core.ZestPlugin;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * A cached label to improve performance of text drawing under linux
+ * @author Ian Bull
+ *
+ */
+public abstract class CachedLabel extends Label {
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.draw2d.Label#paintFigure(org.eclipse.draw2d.Graphics)
+	 */
+	Image cachedImage = null;
+	boolean cacheLabel = false;
+	boolean invalidationRequired = false;
+	
+
+	/**
+	 * CachedLabel constructor.  
+	 * @param cacheLabel Should the label be cached, or should the text be re-layedout each time
+	 */
+	public CachedLabel(boolean cacheLabel) {
+		this.cacheLabel = cacheLabel;
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.draw2d.Label#setIcon(org.eclipse.swt.graphics.Image)
+	 */
+	public void setIcon(Image image) {
+		updateInvalidation();
+		super.setIcon(image);
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#setForegroundColor(org.eclipse.swt.graphics.Color)
+	 */
+	public void setForegroundColor(Color fg) {
+		updateInvalidation();
+		super.setForegroundColor(fg);
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#setBackgroundColor(org.eclipse.swt.graphics.Color)
+	 */
+	public void setBackgroundColor(Color bg) {
+		updateInvalidation();
+		super.setBackgroundColor(bg);
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#setFont(org.eclipse.swt.graphics.Font)
+	 */
+	public void setFont(Font f) {
+		updateInvalidation();
+		super.setFont(f);
+	}
+	
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.draw2d.Label#setText(java.lang.String)
+	 */
+	public void setText(String s) {
+		updateInvalidation();
+		super.setText(s);
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#setSize(int, int)
+	 */
+	public void setSize(int w, int h) {
+		updateInvalidation();
+		
+		if ( cachedImage != null && shouldInvalidateCache() ) {
+			cleanImage();
+		}
+		super.setSize(w, h);
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#setBounds(org.eclipse.draw2d.geometry.Rectangle)
+	 */
+	public void setBounds(Rectangle rect) {
+		boolean resize = (rect.width != bounds.width) || (rect.height != bounds.height);
+	
+		if ( resize && Animation.isAnimating() ) {
+			updateInvalidation();
+		}
+		if ( resize && shouldInvalidateCache() && cachedImage != null) {
+			cleanImage();
+		}
+			
+		super.setBounds(rect);
+	}
+	
+
+	/**
+	 * Override this method to return the background colour for the text
+	 * Note: Text must have a background color since it is being stored in 
+	 * an image (You can set it to white if you want)
+	 * @return
+	 */
+	protected abstract Color getBackgroundTextColor();	
+		
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.draw2d.Label#paintFigure(org.eclipse.draw2d.Graphics)
+	 */
+	protected void paintFigure(Graphics graphics) {
+		if ( !cacheLabel ) {
+			super.paintFigure(graphics);
+			return;
+		}
+		
+		if (isOpaque())
+			graphics.fillRectangle(getBounds());
+		Rectangle bounds = getBounds();
+		graphics.translate(bounds.x, bounds.y);
+		
+		Image icon = getIcon();
+		
+		if (icon != null)
+			graphics.drawImage(icon, getIconLocation());	
+
+		int width = getSubStringTextSize().width;
+		int height = getSubStringTextSize().height;
+
+		if (cachedImage == null || shouldInvalidateCache()) {
+			invalidationRequired = false;	
+			cleanImage();
+			cachedImage = new Image(Display.getCurrent(), width, height);
+			
+			ZestPlugin.getDefault().addImage(cachedImage.toString(), cachedImage);
+			
+			GC gc = new GC(cachedImage);
+			
+			Graphics graphics2 = new SWTGraphics(gc);
+			graphics2.setBackgroundColor(getBackgroundTextColor());
+			graphics2.fillRectangle(0,0,width,height);
+			graphics2.setForegroundColor(getForegroundColor());
+			graphics2.drawText(getSubStringText(),new Point(0,0));
+			gc.dispose();
+			
+		}
+		graphics.drawImage(cachedImage, getTextLocation());
+		graphics.translate(-bounds.x, -bounds.y);
+		this.paintBorder(graphics);
+		
+	}
+	
+	/**
+	 * Determine if the image should be remade or not
+	 * @return
+	 */
+	private boolean shouldInvalidateCache() {
+		if ( invalidationRequired && !Animation.isAnimating())
+			return true;
+		else
+			return false;
+	}
+	
+	/**
+	 * Notifies the cache that the image will need updating.
+	 */
+	private void updateInvalidation() {
+		invalidationRequired = true;
+	}	
+	
+	protected void cleanImage() {
+		if ( cachedImage != null ) {
+			
+			ZestPlugin.getDefault().removeImage(cachedImage.toString());
+			cachedImage.dispose();
+			cachedImage = null;
+		}
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/GraphRootEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/GraphRootEditPart.java
new file mode 100644
index 0000000..3f29fc3
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/GraphRootEditPart.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import java.util.List;
+
+import org.eclipse.draw2d.ConnectionLayer;
+import org.eclipse.draw2d.FreeformLayer;
+import org.eclipse.draw2d.FreeformLayeredPane;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.LayeredPane;
+import org.eclipse.draw2d.ScalableFigure;
+import org.eclipse.draw2d.Viewport;
+import org.eclipse.gef.DragTracker;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
+import org.eclipse.gef.editparts.ZoomManager;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphEditPart;
+import org.eclipse.mylar.zest.core.internal.viewers.trackers.PanningTracker;
+import org.eclipse.mylar.zest.core.internal.viewers.trackers.SingleSelectionTracker;
+
+
+
+/**
+ * Extends {@link org.eclipse.gef.editparts.ScalableFreeformRootEditPart ScalableFreeformRootEditPart} 
+ * to give the option of using a {@link SingleSelectionTracker SingleSelectionTracker} 
+ * instead of a marquee drag tracker.  A PanningDragTracker will be used if the background is 
+ * dragged and marquee selection is not 
+ * 
+ * @author Chris Callendar
+ */
+public class GraphRootEditPart extends ScalableFreeformRootEditPart implements ZestRootEditPart {
+
+
+	
+	private IPanningListener panningListener;
+	private boolean allowMarqueeSelection;
+	private boolean allowPanning;
+	protected GraphEditPart graphEditPart = null;
+	private ZoomManager zoomManager;
+	
+	public GraphRootEditPart() {
+		this(null, false, false);
+	}
+	
+	/**
+	 * Initializes this root edit part.
+	 * @param panningListener the listener to be notified of panning events (dragging the canvas)
+	 * @param allowMarqueeSelection if marquee selection is allowed - multiple node selection
+	 * @param allowPanning if panning is allowed.  Only one of panning OR marquee selection is allowed.
+	 */
+	public GraphRootEditPart(IPanningListener panningListener, boolean allowMarqueeSelection, boolean allowPanning) {
+		super();
+		this.panningListener = panningListener;
+		this.allowMarqueeSelection = allowMarqueeSelection;
+		this.allowPanning = allowPanning;
+		//@tag zest.bug.163481-NPE.fix : moved initialization from the no-arg constructor to here.
+		this.zoomManager = new RectangleZoomManager((ScalableFigure)getScaledLayers(),(Viewport)getFigure());
+	}
+	
+	protected LayeredPane createPrintableLayers() {
+		FreeformLayeredPane layeredPane = new FreeformLayeredPane();
+		
+		layeredPane.add(new ConnectionLayer(), CONNECTION_LAYER);
+		layeredPane.add(new FreeformLayer(), PRIMARY_LAYER);
+		layeredPane.add(new ConnectionLayer(), CONNECTION_FEEDBACK_LAYER);
+		
+		return layeredPane;
+	}
+	
+	/**
+	 * Returns a drag tracker.  If panning is allowed then a PanningTracker is returned.  
+	 * Otherwise either a {@link SingleSelectionTracker} (marqueeSelection disabled)
+	 * or a {@link org.eclipse.gef.tools.MarqueeDragTracker} is returned. 
+	 * @see org.eclipse.gef.editparts.ScalableRootEditPart#getDragTracker(org.eclipse.gef.Request)
+	 */
+	public DragTracker getDragTracker(Request req) {
+		if (allowPanning && (panningListener != null)) {
+			return new PanningTracker(this, panningListener, allowPanning);
+		} else if (!allowMarqueeSelection) {
+			return new SingleSelectionTracker(this);
+		}
+		return super.getDragTracker(req);
+	}
+
+	/**
+	 * Sets the main edit part for the model. You should be able to 
+	 * fire changes off here and see the effect
+	 */
+	public void setModelRootEditPart(Object modelRootEditPart) {
+		this.graphEditPart = (GraphEditPart) modelRootEditPart;
+	}
+	
+	public void clear() {
+//		force revmoval of the edit parts.
+		EditPart[] children = (EditPart[])getChildren().toArray(new EditPart[] {});
+		for (int i = 0; i < children.length; i++) {
+			EditPart child = children[i];
+			removeChild(child);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#unregisterVisuals()
+	 */
+	 //@tag bug(154412-ClearStatic(fix)) : make sure that all the visuals are deregistered before recreating the parts.
+	protected void unregisterVisuals() {
+		super.unregisterVisuals();
+		List children = getFigure().getChildren();
+		//remove all the child figures for the root, which
+		//don't necessarilly have edit parts.
+		for (int i = 0; i < children.size(); i++) {
+			IFigure child = (IFigure) children.get(i);
+			getViewer().getVisualPartMap().remove(child);
+		}
+		getViewer().getVisualPartMap().remove(figure);
+	}
+	
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#unregisterModel()
+	 */
+	 //@tag bug(154412-ClearStatic(fix)) : make sure that all edit parts are removed before creating new ones.
+	protected void unregisterModel() {
+		clear();
+		super.unregisterModel();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.ScalableFreeformRootEditPart#getZoomManager()
+	 */
+	public ZoomManager getZoomManager() {
+		return zoomManager;
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/IPanningListener.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/IPanningListener.java
new file mode 100644
index 0000000..82d34db
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/IPanningListener.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+/**
+ * An interface used for handling panning events.
+ * 
+ * @author Chris Callendar
+ */
+public interface IPanningListener {
+
+    /**
+     * Indicates that panning has started.    
+     */
+    public void panningStart();
+    
+    /**
+     * Handles a change in position due to panning.  
+     * @param dx	the change in x position
+     * @param dy	the change in y position
+     */
+    public void panning(int dx, int dy);
+    
+    /**
+     * Indicates that panning has ceased.  
+     */
+    public void panningEnd();
+    
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/IZestViewerProperties.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/IZestViewerProperties.java
new file mode 100644
index 0000000..e560f1d
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/IZestViewerProperties.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+/**
+ * An experimental interface used for publishing property changes on Zest graphical edit
+ * part viewers.
+ * @author Del Myers
+ *
+ */
+//@tag zest.experimental
+public interface IZestViewerProperties {
+	/**
+	 * Allows viewer listeners to know when the contents of the viewer has changed.
+	 */
+	//@tag zest.experimental.contents.
+	static final String GRAPH_VIEWER_CONTENTS = "zest.viewer.contents"; //$NON-NLS-1$
+	
+}
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/NestedNonThreadedGraphicalViewer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/NestedNonThreadedGraphicalViewer.java
new file mode 100644
index 0000000..3950f5f
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/NestedNonThreadedGraphicalViewer.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.gef.DefaultEditDomain;
+import org.eclipse.gef.EditDomain;
+import org.eclipse.gef.MouseWheelHandler;
+import org.eclipse.gef.MouseWheelZoomHandler;
+import org.eclipse.gef.ui.parts.GraphicalViewerImpl;
+import org.eclipse.mylar.zest.layouts.progress.ProgressEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * 
+ * @author Ian Bull
+ * @author Chris Callendar
+ */
+public abstract class NestedNonThreadedGraphicalViewer extends GraphicalViewerImpl {
+
+	private List revealListeners = null;
+	
+	
+	/**
+	 * @see org.eclipse.gef.EditPartViewer#createControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public Control createControl(Composite composite) {
+		setControl(new Canvas(composite, SWT.DOUBLE_BUFFERED));
+		return getControl();
+	}
+	
+	/**
+	 * ThreadedGraphicalViewer constructor.
+	 * @param parent The composite that this viewer will be added to.
+	 */
+	public NestedNonThreadedGraphicalViewer(Composite parent)  {
+		super();
+		init(parent);
+		EditDomain ed = new DefaultEditDomain( null );
+		ed.addViewer( this );
+		setEditDomain( ed );
+	
+	}
+	
+	protected void init(Composite parent) {
+		// create the FigureCanvas
+		revealListeners = new ArrayList(1);
+		Control oldControl = getControl();
+		if ( oldControl != null ) oldControl.dispose();
+		
+		createControl(parent);
+		hookControl();
+
+		getControl().addPaintListener(new PaintListener() {
+			public void paintControl(PaintEvent e) {
+				if (!revealListeners.isEmpty()) {
+					// Go through the reveal list and let everyone know that the view
+					// is now available.  Remove the listeners so they are only called once!
+					Iterator iterator = revealListeners.iterator();
+					while (iterator.hasNext() ) {
+						RevealListener reveallisetner =  (RevealListener) iterator.next();
+						reveallisetner.revealed(getControl());
+						iterator.remove();
+					}
+				}
+			}
+			
+		});
+		getControl().addControlListener(new ControlListener() {
+
+			public void controlMoved(ControlEvent e) {
+				fireControlMovedEvent( e );
+			}
+
+			public void controlResized(ControlEvent e) {
+				fireControlResizedEvent( e );
+			}
+		});
+		
+		getControl().addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+			}
+		});
+	
+		
+		((Canvas)getControl()).setBackground( ColorConstants.white );
+		
+		// Scroll-wheel Zoom
+		setProperty(MouseWheelHandler.KeyGenerator.getKey(SWT.MOD1), MouseWheelZoomHandler.SINGLETON);		
+	}
+	
+	private List controlListeners = new LinkedList();
+	
+	public void addControlListener( ControlListener controlListener ) {
+		controlListeners.add( controlListener );
+	}
+	
+	
+	/**
+	 * Adds a reveal listener to the view.  Note:  A reveal listener will
+	 * only every be called ONCE!!! even if a view comes and goes. There 
+	 * is no remove reveal listener.
+	 * @param revealListener
+	 */
+	public void addRevealListener( RevealListener revealListener ) {
+		if ( getControl().isVisible() ) revealListener.revealed( (Composite)getControl() );
+		else {
+			revealListeners.add(revealListener);
+		}
+	}
+	
+	public boolean removeControlListener( ControlListener controlListener ) {
+		return controlListeners.remove( controlListener );
+	}
+	
+	protected void fireControlMovedEvent( ControlEvent e ) {
+		for ( Iterator iterator = controlListeners.iterator(); iterator.hasNext(); ) {
+			((ControlListener)iterator.next()).controlMoved( e );
+		}
+	}
+	
+	protected void fireControlResizedEvent( ControlEvent e ) {
+		for ( Iterator iterator = controlListeners.iterator(); iterator.hasNext(); ) {
+			((ControlListener)iterator.next()).controlResized( e );
+		}
+	}
+	
+	
+	
+	
+	/**
+	 * Does some initializing of the viewer.
+	 */
+	protected abstract void configureGraphicalViewer();
+		
+	/**
+	 * Sets the contents of the viewer and configures the graphical viewer.
+	 * @param model
+	 */
+	public void setContents(Object model) {
+		this.configureGraphicalViewer();
+		super.setContents(model);
+	}
+	
+	/**
+	 * Updates the contents <b>without</b> configuring the graphical viewer.
+	 * Only call this if the graphical viewer has already be configured.
+	 * @param model
+	 */
+	public void updateContents(Object model) {
+		super.setContents(model);
+	}
+
+	/**
+	 * Gets the absolute size of the canvas.
+	 * @return Dimension in absolute coords
+	 */
+	public Dimension getCanvasSize() {
+		Dimension dim = new Dimension(this.getControl().getSize());
+		//dim.shrink(getRootFigure().getBorderWidth(), getRootFigure().getBorderWidth());
+		return dim;
+	}
+		
+	/**
+	 * Gets the translated size of the canvas.
+	 * @return Dimension relative
+	 */
+	public Dimension getTranslatedCanvasSize() {
+		Dimension dim = getCanvasSize();
+		//mainCanvas.getViewport().translateToRelative(dim);
+		return dim;
+	}
+		
+	/**
+	 *  
+	 */
+	public void progressUpdated(ProgressEvent e) {
+		//TODO: Make this use the display thread
+	}
+	
+	public void progressEnded(ProgressEvent e) {
+		// TODO Auto-generated method stub
+	}
+	
+	public void progressStarted(ProgressEvent e) {
+		// TODO Auto-generated method stub
+	}	
+
+}
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/NonThreadedGraphicalViewer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/NonThreadedGraphicalViewer.java
new file mode 100644
index 0000000..ec9e512
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/NonThreadedGraphicalViewer.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.gef.DefaultEditDomain;
+import org.eclipse.gef.EditDomain;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.MouseWheelHandler;
+import org.eclipse.gef.MouseWheelZoomHandler;
+import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * 
+ * @author Ian Bull
+ * @author Chris Callendar
+ */
+public abstract class NonThreadedGraphicalViewer extends ScrollingGraphicalViewer {
+
+	private List revealListeners = null;
+	
+	/**
+	 * ThreadedGraphicalViewer constructor.
+	 * @param parent The composite that this viewer will be added to.
+	 */
+	public NonThreadedGraphicalViewer(Composite parent)  {
+		super();
+		
+		revealListeners = new ArrayList(1);
+		
+		// create the FigureCanvas
+		createControl(parent);
+		EditDomain ed = new DefaultEditDomain( null );
+		ed.addViewer( this );
+		setEditDomain( ed );
+		hookControl();
+		//getFigureCanvas().setScrollBarVisibility(FigureCanvas.NEVER);
+		
+
+		getControl().addPaintListener(new PaintListener() {
+			public void paintControl(PaintEvent e) {
+				if (!revealListeners.isEmpty()) {
+					// Go through the reveal list and let everyone know that the view
+					// is now available.  Remove the listeners so they are only called once!
+					Iterator iterator = revealListeners.iterator();
+					while (iterator.hasNext() ) {
+						RevealListener reveallisetner =  (RevealListener) iterator.next();
+						reveallisetner.revealed(getControl());
+						iterator.remove();
+					}
+				}
+			}
+			
+		});
+
+		getControl().addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+			}
+		});
+	
+		((Canvas)getControl()).setBackground( ColorConstants.white );
+		
+		// Scroll-wheel Zoom
+		setProperty(MouseWheelHandler.KeyGenerator.getKey(SWT.MOD1), MouseWheelZoomHandler.SINGLETON);		
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.gef.ui.parts.ScrollingGraphicalViewer#reveal(org.eclipse.gef.EditPart)
+	 */
+	public void reveal(EditPart part) {
+		// @tag rootEditPart : Don't reveal root edit parts
+		if  (!(part instanceof GraphRootEditPart))
+			super.reveal(part);
+	}
+	
+	private class MyRunnable implements Runnable{
+		boolean isVisible;
+		public void run() { isVisible = getControl().isVisible();}
+	}
+	
+	/**
+	 * Adds a reveal listener to the view.  Note:  A reveal listener will
+	 * only every be called ONCE!!! even if a view comes and goes. There 
+	 * is no remove reveal listener.
+	 * @param revealListener
+	 */
+	public void addRevealListener( final RevealListener revealListener ) {
+		
+		MyRunnable myRunnable = new MyRunnable();
+		PlatformUI.getWorkbench().getDisplay().syncExec( myRunnable);
+		
+		if ( myRunnable.isVisible ) 
+			revealListener.revealed( (Composite)getControl() );
+		else 
+			revealListeners.add(revealListener);
+	}
+	
+	/**
+	 * Does some initializing of the viewer.
+	 */
+	protected abstract void configureGraphicalViewer();
+		
+	/**
+	 * Sets the contents of the viewer and configures the graphical viewer.
+	 * @param model
+	 */
+	public void setContents(Object model) {
+		this.configureGraphicalViewer();
+		super.setContents(model);
+		//@tag zest.experimental.contents : publish a property change that the model has changed. This will allow linked viewers to update.
+		setProperty(IZestViewerProperties.GRAPH_VIEWER_CONTENTS, model);
+		
+	}
+	
+	/**
+	 * Updates the contents <b>without</b> configuring the graphical viewer.
+	 * Only call this if the graphical viewer has already be configured.
+	 * @param model
+	 */
+	public void updateContents(Object model) {
+		super.setContents(model);
+		//@tag zest.experimental.contents : publish a property change that the model has changed. This will allow linked viewers to update.
+		setProperty(IZestViewerProperties.GRAPH_VIEWER_CONTENTS, model);
+	}
+
+	/**
+	 * Gets the absolute size of the canvas.
+	 * @return Dimension in absolute coords
+	 */
+	public Dimension getCanvasSize() {
+		Dimension dim = new Dimension(getFigureCanvas().getSize());
+		dim.shrink(getFigureCanvas().getBorderWidth(), getFigureCanvas().getBorderWidth());
+		return dim;
+	}
+		
+	/**
+	 * Gets the translated size of the canvas.
+	 * @return Dimension relative
+	 */
+	public Dimension getTranslatedCanvasSize() {
+		Dimension dim = getCanvasSize();
+		//mainCanvas.getViewport().translateToRelative(dim);
+		return dim;
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/PolylineArcConnection.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/PolylineArcConnection.java
new file mode 100644
index 0000000..7b60173
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/PolylineArcConnection.java
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.draw2d.PolylineConnection;
+import org.eclipse.draw2d.RectangleFigure;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+
+/**
+ * A connection that draws an arc between nodes, based on a given depth for the
+ * arc. This connection is drawn as an arc,
+ * defined as the circular arc with the chord (ax, ay) - (bx, by) (where a and b
+ * are the anchors) and a depth d defined as the maximum distance from any point on
+ * the chord (i.e. a vector normal to the chord with magnitude d).
+ * 
+ * @author Del Myers
+ *
+ */
+//@tag zest(bug(154391-ArcEnds(fix))) : force the endpoints to match by using a polyline connection.
+//This will be more accurate than the regular ArcConnection, but it may be slower.
+public class PolylineArcConnection extends PolylineConnection {
+	private int depth;
+	private static final float PI = (float)3.14;
+	private RectangleFigure center;
+	
+
+	{
+		this.depth=0;
+		center = new RectangleFigure();
+	}
+		
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Polyline#setPoints(org.eclipse.draw2d.geometry.PointList)
+	 */
+	public void setPoints(PointList points) {
+		updateArc(points);
+	}
+	
+	/**
+	 * This method is not supported by this kind of connection. Points are
+	 * calculated based on the arc definition.
+	 */
+	public void addPoint(Point pt) {
+	}
+	
+	/**
+	 * @param depth the depth to set
+	 */
+	public void setDepth(int depth) {
+		this.depth = depth;
+		updateArc(getPoints());
+	}
+	
+	protected void updateArc(PointList pointList) {
+		if (pointList.size() < 2) return;
+		if (center.getParent() == this) remove(center);
+		Point start = pointList.getFirstPoint();
+		Point end = pointList.getLastPoint();
+		
+		if (depth == 0) {
+			super.setPoints(pointList);
+			return;
+		}
+		
+		PointList points = new PointList();
+		
+		float arcStart = 0;
+		float arcLength = 0;
+		float cartCenterX = 0;
+		float cartCenterY = 0;
+		float r = 0;
+		
+		float x1 = start.x;
+		float y1 = -start.y;
+		float x2 = end.x;
+		float y2 = -end.y;
+		float depth = this.depth;
+				
+		if (start.equals(end)) {
+			//do a circle
+			arcStart = -PI/2;
+			arcLength = PI*2;
+//			@tag drawing(arcs) : try making the center on a line from the center of the parent figure.
+			
+			cartCenterX = x1;
+			cartCenterY = y1+depth/2;
+			r = depth/2;
+			
+		} else {
+			if (x1 >= x2) {
+				depth = -depth;
+			}
+			//		the center of the chord
+			float cartChordX = (x2 + x1)/2;
+			float cartChordY = (y2 + y1)/2;
+			float chordLength = (float)Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
+			if (Math.abs(depth) >= chordLength/2) {
+				depth = (chordLength/3)*(depth/Math.abs(depth));
+			}
+			r = ((((chordLength/2)*(chordLength/2)) + ((float)depth*depth))/((float)2*depth));
+
+			//Find a vector normal to the chord. This will be used for translating the
+			//circle back to screen coordinates.
+			float chordNormal = 0;
+
+			if (Math.abs(x1 - x2) <= .001) {
+				//slope of 0. NaN is easier to detect than 0.
+				chordNormal = Float.NaN;
+			} else if (Math.abs(y1-y2) <= 0.001) {
+				//infinite slope.
+				chordNormal = Float.POSITIVE_INFINITY;
+			} else {
+				chordNormal = -(float)(y2 - y1)/(x2 - x1);
+			}
+
+			float th1;
+			if (Float.isNaN(chordNormal)) {
+				cartCenterX = (y1 > y2) ? (cartChordX-r+(depth)) : (cartChordX+r-(depth));
+				cartCenterY = cartChordY;
+				th1 = PI/2;
+			} else if (Float.isInfinite(chordNormal)) {
+				cartCenterX = cartChordX;
+				cartCenterY = cartChordY+r-(depth);
+				th1 = 0;
+			} else {
+				//assume that the center of the chord is on the origin.
+				th1 = (float)Math.atan(chordNormal);
+				cartCenterX = (r-(depth))*(float)Math.sin(th1)+cartChordX;//cartChordX+r -depth;
+				cartCenterY = (r-(depth))*(float)Math.cos(th1)+cartChordY;//cartChordY+r-depth;
+
+			}
+			//figure out the new angles
+			//translate the points to the center of the circle
+			float cartArcX1 = x1 - cartCenterX;
+			float cartArcY1 = y1 - cartCenterY;
+			float cartArcX2 = x2 - cartCenterX;
+			float cartArcY2 = y2 - cartCenterY;
+
+			//calculate the length of the arc
+			arcStart = angleRadians(cartArcX1, cartArcY1);
+			float arcEnd = angleRadians(cartArcX2, cartArcY2);
+			
+			if (arcEnd < arcStart) {
+				arcEnd = arcEnd + PI + PI;
+			}
+						
+			//make sure that we are between the two nodes.
+			arcLength = arcEnd-arcStart;
+			float pad = PI/(float)Math.abs(r);
+			arcStart += pad;
+			arcEnd -= pad;
+			arcLength = (arcEnd)-(arcStart);
+		}
+		//calculate the points
+		r = Math.abs(r);
+		float x=0, y=0;
+		Point p=null;
+		points.addPoint(start);
+		float length = arcLength*r;
+		
+		int steps = (int)length/16;
+		if (steps < 10 && length > 10) steps = 10;
+		if (arcLength < PI/4 && steps > 6) steps = 6;
+		if (steps < 4 && length > 4) 
+			steps = 4;
+		float stepSize = arcLength/steps;
+		float step = stepSize+arcStart;
+		for (int i = 1; i < steps; i++, step+= stepSize) {
+			x = (r)*(float)Math.cos(step) + cartCenterX;
+			y = (r)*(float)Math.sin(step) + cartCenterY;
+			p = new Point((int)Math.round(x), (int)Math.round(-y));
+			points.addPoint(p);
+		}
+		points.addPoint(end);
+		
+		
+		super.setPoints(points);
+	}
+	
+
+	/*
+	 * Gets an angle in radians for the x, y coordinates. The angle will be between 0 and 2PI. 
+	 */
+	float angleRadians(float x, float y) {
+		float theta = (float)Math.atan(y/x);
+		switch (findQuadrant(x,y)) {
+			case 1: return theta;
+			case 2: return (theta+PI);
+			case 4: theta = (theta+PI);
+			case 3: return (theta+PI);	 
+			default: return theta;
+		}
+		
+	}
+	
+	//find the quadrant, assume points are centered at 0,0
+	protected int findQuadrant (float x, float y) {
+		if (y > 0) {
+			if (x > 0) {
+				return 1;
+			} else {
+				return 2;
+			}
+		} else {
+			if (x > 0) {
+				return 4;
+			} else {
+				return 3;
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/RectangleZoomManager.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/RectangleZoomManager.java
new file mode 100644
index 0000000..4d59726
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/RectangleZoomManager.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.draw2d.ScalableFigure;
+import org.eclipse.draw2d.Viewport;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.editparts.ZoomManager;
+
+/**
+ * A zoom manager that has support for the zoomTo method.
+ * @author Del Myers
+ *
+ */
+public class RectangleZoomManager extends ZoomManager {
+
+	/**
+	 * @param pane
+	 * @param viewport
+	 */
+	public RectangleZoomManager(ScalableFigure pane, Viewport viewport) {
+		super(pane, viewport);
+	}
+	
+	/**
+	 * Takes a rectangle in the viewport coordinates, that is not scaled according
+	 * to the current viewport scale. Scales the viewport to which ever axis of the
+	 * rectangle holds the most information.
+	 */
+	public void zoomTo(Rectangle rect) {
+		//figure out the scale.
+		Rectangle vbounds = getViewport().getBounds().getCopy();
+		Point center = rect.getCenter();
+		Rectangle copy = rect.getCopy();
+		
+		double scale = 1;
+		if (rect.isEmpty()) {
+			//do nothing
+		} else if (rect.width < rect.height) {
+			scale = ((double)vbounds.height)/copy.height;
+			copy.scale(scale,1);
+		} else {
+			scale = ((double)vbounds.width)/copy.width;
+			copy.scale(1,scale);
+		}
+		center.scale(scale);
+		primSetZoom(scale);
+		Rectangle clientArea = getViewport().getClientArea();
+		setViewLocation(new Point(center.x - clientArea.width/2, center.y - clientArea.height/2));
+	}
+
+	
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/RevealListener.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/RevealListener.java
new file mode 100644
index 0000000..d8d6c6e
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/RevealListener.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * 
+ * A Listener to indicate when a view has become visible.
+ * @author Ian Bull
+ *
+ */
+public interface RevealListener {
+	
+	public void revealed( Control c );
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/StaticGraphRootEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/StaticGraphRootEditPart.java
new file mode 100644
index 0000000..9921b44
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/StaticGraphRootEditPart.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.draw2d.ConnectionLayer;
+import org.eclipse.draw2d.FreeformLayer;
+import org.eclipse.draw2d.FreeformLayeredPane;
+import org.eclipse.draw2d.LayeredPane;
+import org.eclipse.gef.DragTracker;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.tools.MarqueeDragTracker;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphEditPart;
+import org.eclipse.mylar.zest.core.internal.viewers.trackers.PanningTracker;
+import org.eclipse.mylar.zest.core.internal.viewers.trackers.SingleSelectionTracker;
+
+
+
+/**
+ * Extends {@link org.eclipse.gef.editparts.ScalableFreeformRootEditPart ScalableFreeformRootEditPart} 
+ * to give the option of using a {@link SingleSelectionTracker SingleSelectionTracker} 
+ * instead of a marquee drag tracker.  A PanningDragTracker will be used if the background is 
+ * dragged and marquee selection is not 
+ * 
+ * @author Chris Callendar
+ */
+public class StaticGraphRootEditPart extends GraphRootEditPart implements ZestRootEditPart {
+
+	public static final String CONNECTION_FEEDBACK_LAYER = "Connection Feedback Layer"; //$NON-NLS-1$
+	
+	private IPanningListener panningListener;
+	private boolean allowMarqueeSelection;
+	private boolean allowPanning;
+	private GraphEditPart modelGraphEditPart = null;
+	
+	public StaticGraphRootEditPart() {
+		super();
+	}
+	/**
+	 * Initializes this root edit part.
+	 * @param panningListener the listener to be notified of panning events (dragging the canvas)
+	 * @param allowMarqueeSelection if marquee selection is allowed - multiple node selection
+	 * @param allowPanning if panning is allowed.  Only one of panning OR marquee selection is allowed.
+	 */
+	//@tag zest.bug.156617ClearViewer.fix : have to configure the edit part after it is created.
+	public void configure(IPanningListener panningListener, boolean allowMarqueeSelection, boolean allowPanning) {
+		this.panningListener = panningListener;
+		this.allowMarqueeSelection = allowMarqueeSelection;
+		this.allowPanning = allowPanning;
+		
+	}
+	
+	protected LayeredPane createPrintableLayers() {
+		FreeformLayeredPane layeredPane = new FreeformLayeredPane();
+		layeredPane.add(new ConnectionLayer(), CONNECTION_LAYER);
+		layeredPane.add(new FreeformLayer(), PRIMARY_LAYER);
+		layeredPane.add(new ConnectionLayer(), CONNECTION_FEEDBACK_LAYER);
+		
+		return layeredPane;
+	}
+	
+	/**
+	 * Returns a drag tracker.  If panning is allowed then a PanningTracker is returned.  
+	 * Otherwise either a {@link SingleSelectionTracker} (marqueeSelection disabled)
+	 * or a {@link org.eclipse.gef.tools.MarqueeDragTracker} is returned. 
+	 * @see org.eclipse.gef.editparts.ScalableRootEditPart#getDragTracker(org.eclipse.gef.Request)
+	 */
+	public DragTracker getDragTracker(Request req) {
+		if (allowPanning && (panningListener != null)) {
+			return new PanningTracker(this, panningListener, allowPanning);
+		} else if (!allowMarqueeSelection) {
+			// If we don't allow the marquee selection use our drag tracker
+			return new ViewerDragTracker(this);
+		}
+		return new MarqueeDragTracker();
+	}
+	/**
+	 * Sets the scale for the Static Graph Viewer
+	 * @param x
+	 * @param y
+	 */
+	public void setScale( double x, double y ) {
+		this.modelGraphEditPart.setScale(x, y);
+
+	}
+	
+	/**
+	 * Gets the scale in the X Direction
+	 * @return
+	 */
+	public double getXScale() {
+		return this.modelGraphEditPart.getXScale();
+	}
+
+	
+	/**
+	 * Gets the scale in the Y Direction
+	 * @return
+	 */
+	public double getYScale() {
+		return this.modelGraphEditPart.getYScale();
+	}
+
+	
+	/**
+	 * Sets the model root edit part.  You should be able to set 
+	 * changes here and see the effect.
+	 */
+	public void setModelRootEditPart(Object modelRootEditPart) {
+		this.modelGraphEditPart = (GraphEditPart) modelRootEditPart;
+	}
+	
+	//@tag zest.bug.156286-Zooming : expose the graph edit part so that the zoom manager can be found.
+	public GraphEditPart getModelRootEditPart() {
+		return modelGraphEditPart;
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ThreadedGraphicalEditor.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ThreadedGraphicalEditor.java
new file mode 100644
index 0000000..caaa338
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ThreadedGraphicalEditor.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.draw2d.DeferredUpdateManager;
+import org.eclipse.draw2d.LightweightSystem;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.gef.GraphicalViewer;
+import org.eclipse.gef.ui.parts.GraphicalEditor;
+import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer;
+import org.eclipse.mylar.zest.layouts.progress.ProgressEvent;
+import org.eclipse.mylar.zest.layouts.progress.ProgressListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * 
+ * @author Ian Bull
+ *
+ */
+public abstract class ThreadedGraphicalEditor extends GraphicalEditor implements ProgressListener {	
+	
+	
+	class MyScrollingGraphicalViewer extends ScrollingGraphicalViewer {
+
+		
+		class MyLightWeightSystem extends LightweightSystem {
+			
+			class DisplaySynchronize implements Runnable {
+					GC _gc = null;
+					public DisplaySynchronize( GC gc ) {
+						_gc = gc;
+					}
+		
+					public void run() {
+						MyLightWeightSystem.this._paint( _gc );
+					}	
+			}
+		
+			public void paint(GC gc) {
+				Display.getDefault().syncExec(new DisplaySynchronize( gc ) );
+			}
+			
+			private void _paint( GC gc ) {
+				super.paint( gc );
+			}
+		}
+		
+		class MyUpdateManager extends DeferredUpdateManager {
+			class DisplaySynchronize implements Runnable {
+	
+				public void run() {
+					MyUpdateManager.this._queueWork(  );
+				}
+
+			}
+			
+			public void queueWork( ) {
+				//Display.getDefault().asyncExec(new DisplaySynchronize() );
+				Display.getDefault().syncExec(new DisplaySynchronize() );
+			}
+			
+			public void _queueWork() {
+			   super.queueWork();
+			}
+		}
+		
+		
+		protected LightweightSystem createLightweightSystem() {
+			LightweightSystem lws = new MyLightWeightSystem();
+			lws.setUpdateManager( new MyUpdateManager() );
+			return  lws;
+		}
+		
+	}
+
+	public void progressUpdated(ProgressEvent e) {
+		//TODO: Make this use the display thread
+	}
+	
+	public Dimension getCanvasSize() {
+		//TODO: I don't think this really gets the canvas size
+		Point p =  this.getGraphicalViewer().getControl().getSize();
+		return new Dimension(p.x, p.y );
+	}
+	
+	/**
+	 * Creates the GraphicalViewer on the specified <code>Composite</code>.
+	 * @param parent the parent composite
+	 */
+	protected void createGraphicalViewer(Composite parent) {
+		GraphicalViewer viewer = new MyScrollingGraphicalViewer();	
+		viewer.createControl(parent);
+		setGraphicalViewer(viewer);
+		configureGraphicalViewer();
+		hookGraphicalViewer();
+		initializeGraphicalViewer();
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ThreadedGraphicalViewer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ThreadedGraphicalViewer.java
new file mode 100644
index 0000000..8ecc264
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ThreadedGraphicalViewer.java
@@ -0,0 +1,401 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.DeferredUpdateManager;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.LightweightSystem;
+import org.eclipse.draw2d.UpdateManager;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.DefaultEditDomain;
+import org.eclipse.gef.EditDomain;
+import org.eclipse.gef.ui.parts.GraphicalViewerImpl;
+import org.eclipse.mylar.zest.core.internal.viewers.figures.Graph;
+import org.eclipse.mylar.zest.layouts.Stoppable;
+import org.eclipse.mylar.zest.layouts.progress.ProgressEvent;
+import org.eclipse.mylar.zest.layouts.progress.ProgressListener;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * A Graphical Viewer Imple which  is thread safe.  The update manager syncs with the default thread
+ * before updating anything. This viewer also allows other threads to be added to it.  The threads are added as
+ * "Stoppable" Objects. The stoppables are started when they are added, and when the view
+ * is disposed they are removed.
+ * 
+ * @author Ian Bull
+ *
+ */
+public abstract class ThreadedGraphicalViewer extends GraphicalViewerImpl implements ProgressListener  {
+
+	/** Holds all the threads added to this viewer */
+	private Map listOfThreads = null; 
+	Composite parent = null;
+
+	
+	/**
+	 * ThreadedGraphicalViewer constructor.
+	 * @param parent The composite that this viewer will be added to.
+	 */
+	public ThreadedGraphicalViewer(Composite parent)  {
+		super();
+		this.parent = parent;
+		listOfThreads = new LinkedHashMap();
+		
+		updateManager = getLightweightSystem().getUpdateManager();
+		
+		// Creates a new graph (a FigureCanvas)
+		Canvas canvas = new Graph(parent);
+		canvas.setLayout(new FillLayout());
+		setControl(canvas);
+		
+		EditDomain ed = new DefaultEditDomain( null );
+		ed.addViewer( this );
+		//ed.setDefaultTool(new ZoomableSelectionTool());
+		setEditDomain( ed );
+		
+		hookControl();
+	
+		getControl().addControlListener(new ControlListener() {
+
+			public void controlMoved(ControlEvent e) {
+				fireControlMovedEvent( e );
+			}
+
+			public void controlResized(ControlEvent e) {
+				fireControlResizedEvent( e );
+			}
+		});
+		
+		getControl().addDisposeListener(new DisposeListener() {
+
+			public void widgetDisposed(DisposeEvent e) {
+				removeAllThreads();
+			}
+			
+		});
+		
+		// TODO is this needed?  A focus listener is added inside hookControl() above...
+		getControl().addFocusListener(new FocusListener() {
+			public void focusGained(FocusEvent e) {
+				//handleFocusGained(e);
+			}
+			public void focusLost(FocusEvent e) {
+			}
+		});
+	
+		((Canvas)getControl()).setBackground( ColorConstants.white );
+		
+		FreqUpdater updater = new FreqUpdater();
+		updater.addProgressListener( new ProgressListener() {
+
+			public void progressStarted(ProgressEvent e) {
+				// TODO Auto-generated method stub
+				
+				
+			}
+
+			public void progressUpdated(ProgressEvent e) {
+				// TODO Auto-generated method stub
+				IFigure rootFigure = null;
+				try {
+					 rootFigure = ThreadedGraphicalViewer.this.getLightweightSystem().getRootFigure();
+				}
+				catch ( Exception exception ) {
+					exception.printStackTrace();
+				}
+				
+				if (updateManager != null && rootFigure != null ) 
+					((MyUpdateManager)updateManager)._addInvalidFigure( rootFigure  );
+			}
+
+			public void progressEnded(ProgressEvent e) {
+				// TODO Auto-generated method stub
+				
+			}
+			
+		});
+		
+		addThread( updater );
+		
+
+	}
+	
+	private List controlListeners = new LinkedList();
+	
+	public void addControlListener( ControlListener controlListener ) {
+		controlListeners.add( controlListener );
+	}
+	
+	public boolean removeControlListener( ControlListener controlListener ) {
+		return controlListeners.remove( controlListener );
+	}
+	
+	protected void fireControlMovedEvent( ControlEvent e ) {
+		for ( Iterator iterator = controlListeners.iterator(); iterator.hasNext(); ) {
+			((ControlListener)iterator.next()).controlMoved( e );
+		}
+	}
+	
+	protected void fireControlResizedEvent( ControlEvent e ) {
+		for ( Iterator iterator = controlListeners.iterator(); iterator.hasNext(); ) {
+			((ControlListener)iterator.next()).controlResized( e );
+		}
+	}
+	
+	/**
+	 * Does some initializing of the viewer.
+	 */
+	protected abstract void configureGraphicalViewer();
+	
+	/**
+	 * Sets the contents of the viewer and configures the graphical viewer.
+	 * @param model
+	 */
+	public void setContents(Object model) {
+		this.configureGraphicalViewer();
+		super.setContents(model);
+//		@tag zest.experimental.contents : publish a property change that the model has changed. This will allow linked viewers to update.
+		setProperty(IZestViewerProperties.GRAPH_VIEWER_CONTENTS, model);
+		
+	}
+	
+	/**
+	 * Updates the contents <b>without</b> configuring the graphical viewer.
+	 * Only call this if the graphical viewer has already be configured.
+	 * @param model
+	 */
+	public void updateContents(Object model) {
+		super.setContents(model);
+//		@tag zest.experimental.contents : publish a property change that the model has changed. This will allow linked viewers to update.
+		setProperty(IZestViewerProperties.GRAPH_VIEWER_CONTENTS, model);
+	}
+	
+	/**
+	 * Adds a new thread to this viewer and starts it.
+	 * @param r
+	 */
+	public void addThread( Stoppable r ) {
+		Thread thread = new Thread( r );
+		r.addProgressListener( this );
+		listOfThreads.put( r, thread );
+		thread.setPriority( java.lang.Thread.MAX_PRIORITY );
+		thread.start();
+	}
+	
+	/**
+	 * Gets the absolute size of the canvas.
+	 * @return Dimension in absolute coords
+	 */
+	public Dimension getCanvasSize() {
+		return new Dimension( getFigureCanvas().getSize() );
+	}
+	
+	/**
+	 * Gets the translated size of the canvas.
+	 * @return Dimension relative
+	 */
+	public Dimension getTranslatedCanvasSize() {
+		Dimension dim = getCanvasSize();
+		//getCanvas().get
+		//mainCanvas.getViewport().translateToRelative(dim);
+		return dim;
+	}
+	
+	public Canvas getFigureCanvas() {
+		return (Canvas)getControl();
+	}
+	
+	/**
+	 * Removes and stop the thread
+	 * @param r
+	 */
+	public void removeThread( Stoppable r ) {
+		Thread t = (Thread) listOfThreads.get( r );
+		r.stop();
+		
+		try {
+			t.join( 1000 );
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+		
+		if ( t.isAlive() ) {
+			StackTraceElement[] elements = t.getStackTrace();
+			String stackTrace = "";
+			for (int i = 0; i < elements.length; i++) {
+				stackTrace += elements[i].toString() + "\n";
+			}
+			throw new RuntimeException("Thread didn't stop, stack was: " + stackTrace);
+		}
+		listOfThreads.remove( r );
+	}
+	
+	
+	public void removeAllThreads () {
+		Set keySet = listOfThreads.keySet();
+		Stoppable[] keySetArray = (Stoppable[])keySet.toArray(new Stoppable[keySet.size()]);
+		
+		for ( int i = 0; i < keySetArray.length; i++) {
+			removeThread( keySetArray[i] );
+			
+		}
+	}
+	
+	/**
+	 *  
+	 */
+	public void progressUpdated(ProgressEvent e) {
+		//TODO: Make this use the display thread
+	}
+	
+	public void progressEnded(ProgressEvent e) {
+		// TODO Auto-generated method stub
+	}
+	
+	public void progressStarted(ProgressEvent e) {
+		// TODO Auto-generated method stub
+	}
+	
+	protected LightweightSystem createLightweightSystem() {
+		//return new LightweightSystem();
+		
+		LightweightSystem lws = new MyLightWeightSystem();
+		lws.setUpdateManager( new MyUpdateManager() );
+		
+
+		
+		return  lws;
+		
+	}
+
+	
+class MyLightWeightSystem extends LightweightSystem {
+		
+		class DisplaySynchronize implements Runnable {
+				GC _gc = null;
+				public DisplaySynchronize( GC gc ) {
+					_gc = gc;
+				}
+	
+				public void run() {
+					
+						MyLightWeightSystem.this._paint( _gc );
+
+				}	
+		}
+	
+		public void paint(GC gc) {
+			//DebugPrint.println("My LWS Paint!");
+			if ( getControl().isVisible() )
+				Display.getDefault().syncExec(new DisplaySynchronize( gc ) );
+		}
+		
+		private void _paint( GC gc ) {
+			super.paint( gc );
+		}
+	}
+	
+	class MyUpdateManager extends DeferredUpdateManager {
+		class DisplaySynchronize implements Runnable {
+
+			public void run() {
+				MyUpdateManager.this._queueWork(  );
+			}
+
+		}
+		
+		public synchronized void performUpdate() {
+			// TODO Auto-generated method stub
+//			DebugPrint.println("Perform update called");
+			super.performUpdate();
+		}
+		
+		public synchronized void performUpdate(Rectangle exposed) {
+			// TODO Auto-generated method stub
+//			System.out.println("Perform Updated");
+			super.performUpdate(exposed);
+		}
+		
+		public void queueWork( ) {
+			Display.getDefault().asyncExec(new DisplaySynchronize() );
+		}
+		
+		public void _queueWork() {
+		   super.queueWork();
+		}
+		
+		public synchronized void _addInvalidFigure( IFigure f ) {
+			super.addInvalidFigure( f );
+		}
+		
+		public synchronized void addInvalidFigure(IFigure f) {
+			// TODO Auto-generated method stub
+			super.addInvalidFigure(f);
+			// do nothing
+		}
+		
+	}
+	
+	UpdateManager updateManager = null;
+
+	
+	public class FreqUpdater implements Stoppable {
+
+		//TODO: Why is this here?  It doesn't do anything?
+		ArrayList listOfProgressListeners = new ArrayList();
+
+		public void addProgressListener(ProgressListener listener) {
+			listOfProgressListeners.add( listener );
+		}
+
+		boolean keepGoing = true;
+
+		public void stop() {
+			keepGoing = false;
+		}
+
+		public void run() {
+			while (keepGoing) {
+				if (listOfProgressListeners != null) {
+					//TODO: This is not thread safe
+					for ( int i = 0; i < listOfProgressListeners.size(); i++ ) {
+						((ProgressListener) listOfProgressListeners.get(i)).progressUpdated( null );
+					}
+				}
+				try {
+					Thread.sleep(15);
+				} catch (InterruptedException e) {
+					e.printStackTrace();
+				}
+			}
+		}
+	}	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ViewerDragTracker.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ViewerDragTracker.java
new file mode 100644
index 0000000..7a1f8e1
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ViewerDragTracker.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.tools.SelectEditPartTracker;
+import org.eclipse.swt.events.MouseEvent;
+
+/**
+ * @author Ian Bull
+ * 
+ * This is our basic drag tracker that we use in our graph views.  
+ * The mouse events are handled here.
+ */
+public class ViewerDragTracker extends SelectEditPartTracker {
+
+	public ViewerDragTracker(EditPart owner) {
+		super(owner);
+	}
+	
+	/**
+	 * A Mouse down event has happened on the canvas.  If it is mouse button 1, then 
+	 * we can handle it, otherwise just ignore it.  This means that users can add
+	 * context menus with mouse button 2.  
+	 */
+	public void mouseDown(MouseEvent me, EditPartViewer viewer) {
+		if (me.button == 1 )  
+			super.mouseDown(me, viewer);
+		return;
+	} 
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/XYScaledGraphics.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/XYScaledGraphics.java
new file mode 100644
index 0000000..962252c
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/XYScaledGraphics.java
@@ -0,0 +1,825 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Chisel Group, University of Victoria - Adapted for XY Scaled Graphics
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.draw2d.FigureUtilities;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.ScaledGraphics;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.TextLayout;
+import org.eclipse.swt.graphics.TextStyle;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * This was adapted from the ScaledGraphics class to allow X and Y to scale
+ * independently.  It won't require this level of coupling if some of these
+ * private methods were made protected.  I will open a bug report on this.
+ * 
+ * @author irbull
+ */
+public class XYScaledGraphics extends ScaledGraphics {
+	
+	public static final double MAX_TEXT_SIZE = 0.45; // MAX size, when to stop zooming text
+
+	private static class FontHeightCache {
+		Font font;
+		int height;
+	}
+
+	static class FontKey {
+		Font font;
+		int height;
+		protected FontKey() { }
+		protected FontKey(Font font, int height) {
+			this.font = font;
+			this.height = height;
+		}
+		
+		public boolean equals(Object obj) {
+			return (((FontKey)obj).font.equals(font) 
+					&& ((FontKey)obj).height == height);
+		}
+
+		public int hashCode() {
+			return font.hashCode() ^ height;
+		}
+
+		protected void setValues(Font font, int height) {
+			this.font = font;
+			this.height = height;
+		}
+	}
+
+	/**
+	 * The internal state of the scaled graphics.
+	 */
+	protected static class State {
+		private double appliedX;
+		private double appliedY;
+		private Font font;
+		private int lineWidth;
+		//private double zoom;  // This has been replaced with xZoom and yZoom
+		private double xZoom;
+		private double yZoom;
+
+		/**
+		 * Constructs a new, uninitialized State object.
+		 */
+		protected State() { }
+		
+		/**
+		 * Constructs a new State object and initializes the properties based on the given 
+		 * values.
+		 * 
+		 * @param zoom the zoom factor
+		 * @param x the x offset
+		 * @param y the y offset
+		 * @param font the font
+		 * @param lineWidth the line width
+		 */
+		protected State(double xZoom, double yZoom, double x, double y, Font font, int lineWidth) {
+			this.xZoom = xZoom;
+			this.yZoom = yZoom;
+			this.appliedX = x;
+			this.appliedY = y;
+			this.font = font;
+			this.lineWidth = lineWidth;
+		}
+		
+		/**
+		 * Sets all the properties of the state object.
+		 * @param zoom the zoom factor
+		 * @param x the x offset
+		 * @param y the y offset
+		 * @param font the font
+		 * @param lineWidth the line width
+		 */
+		protected void setValues(double xZoom, double yZoom, double x, double y, 
+									Font font, int lineWidth) {
+			this.xZoom = xZoom;
+			this.yZoom = yZoom;
+			this.appliedX = x;
+			this.appliedY = y;
+			this.font = font;
+			this.lineWidth = lineWidth;
+		}
+	}
+
+	private static int[][] intArrayCache = new int[8][];
+	private final Rectangle tempRECT = new Rectangle();
+
+	static {
+		for (int i = 0; i < intArrayCache.length; i++)
+			intArrayCache[i] = new int[i + 1];
+	}
+
+	private boolean allowText = true;
+//	private static final Point PT = new Point();
+	private Map fontCache = new HashMap();
+	private Map fontDataCache = new HashMap();
+	private FontKey fontKey = new FontKey();
+	private double fractionalX;
+	private double fractionalY;
+	private Graphics graphics;
+	private FontHeightCache localCache = new FontHeightCache();
+	private Font localFont;
+	private int localLineWidth;
+	private List stack = new ArrayList();
+	private int stackPointer = 0;
+	private FontHeightCache targetCache = new FontHeightCache();
+
+	double xZoom = 1.0;
+	double yZoom = 1.0;
+
+	/**
+	 * Constructs a new ScaledGraphics based on the given Graphics object.
+	 * @param g the base graphics object
+	 */
+	public XYScaledGraphics(Graphics g) {
+		super(g);
+		graphics = g;
+		localFont = g.getFont();
+		localLineWidth = g.getLineWidth();
+	}
+
+	/** @see Graphics#clipRect(Rectangle) */
+	public void clipRect(Rectangle r) {
+		graphics.clipRect(zoomClipRect(r));
+	}
+
+	Font createFont(FontData data) {
+		return new Font(Display.getCurrent(), data);
+	}
+
+	/** @see Graphics#dispose() */
+	public void dispose() {
+		//Remove all states from the stack
+		while (stackPointer > 0) {
+			popState();
+		}
+		
+		//Dispose fonts
+		Iterator iter = fontCache.values().iterator();
+		while (iter.hasNext()) {
+			Font font = ((Font)iter.next());
+	 		font.dispose();
+	 	}
+
+	}
+
+	/** @see Graphics#drawArc(int, int, int, int, int, int) */
+	public void drawArc(int x, int y, int w, int h, int offset, int sweep) {
+		Rectangle z = zoomRect(x, y, w, h);
+		if (z.isEmpty() || sweep == 0)
+			return;
+		graphics.drawArc(z, offset, sweep);
+	}
+
+	/** @see Graphics#drawFocus(int, int, int, int) */
+	public void drawFocus(int x, int y, int w, int h) {
+		graphics.drawFocus(zoomRect(x, y, w, h));
+	}
+
+	/** @see Graphics#drawImage(Image, int, int) */
+	public void drawImage(Image srcImage, int x, int y) {
+		org.eclipse.swt.graphics.Rectangle size = srcImage.getBounds();
+		double imageZoom = Math.min(xZoom, yZoom);
+		graphics.drawImage(srcImage, 0, 0, size.width, size.height,
+			(int)(Math.floor((x * xZoom + fractionalX))), 
+			(int)(Math.floor((y * yZoom + fractionalY))),
+			(int)(Math.floor((size.width * imageZoom + fractionalX))), 
+			(int)(Math.floor((size.height * imageZoom + fractionalY))));
+	}
+
+	/** @see Graphics#drawImage(Image, int, int, int, int, int, int, int, int) */
+	public void drawImage(Image srcImage, int sx, int sy, int sw, int sh,
+											int tx, int ty, int tw, int th) {
+		//"t" == target rectangle, "s" = source
+				 
+		Rectangle t = zoomRect(tx, ty, tw, th);
+		if (!t.isEmpty())
+			graphics.drawImage(srcImage, sx, sy, sw, sh, t.x, t.y, t.width, t.height);
+	}
+
+	/** @see Graphics#drawLine(int, int, int, int) */
+	public void drawLine(int x1, int y1, int x2, int y2) {
+		graphics.drawLine(
+			(int)(Math.floor((x1 * xZoom + fractionalX))),
+			(int)(Math.floor((y1 * yZoom + fractionalY))),
+			(int)(Math.floor((x2 * xZoom + fractionalX))),
+			(int)(Math.floor((y2 * yZoom + fractionalY))));
+	}
+
+	/** @see Graphics#drawOval(int, int, int, int) */
+	public void drawOval(int x, int y, int w, int h) {
+		graphics.drawOval(zoomRect(x, y, w, h));
+	}
+
+	/** @see Graphics#drawPoint(int, int) */
+	public void drawPoint(int x, int y) {
+		graphics.drawPoint((int)Math.floor(x * xZoom + fractionalX),
+				(int)Math.floor(y * yZoom + fractionalY));
+	}
+
+	/**
+	 * @see Graphics#drawPolygon(int[])
+	 */
+	public void drawPolygon(int[] points) {
+		graphics.drawPolygon(zoomPointList(points));
+	}
+
+	/** @see Graphics#drawPolygon(PointList) */
+	public void drawPolygon(PointList points) {
+		graphics.drawPolygon(zoomPointList(points.toIntArray()));
+	}
+
+	/**
+	 * @see Graphics#drawPolyline(int[])
+	 */
+	public void drawPolyline(int[] points) {
+		graphics.drawPolyline(zoomPointList(points));
+	}
+
+	/** @see Graphics#drawPolyline(PointList) */
+	public void drawPolyline(PointList points) {
+		graphics.drawPolyline(zoomPointList(points.toIntArray()));
+	}
+
+	/** @see Graphics#drawRectangle(int, int, int, int) */
+	public void drawRectangle(int x, int y, int w, int h) {
+		graphics.drawRectangle(zoomRect(x, y, w, h));
+	}
+
+	/** @see Graphics#drawRoundRectangle(Rectangle, int, int) */
+	public void drawRoundRectangle(Rectangle r, int arcWidth, int arcHeight) {
+		graphics.drawRoundRectangle(zoomRect(r.x, r.y, r.width, r.height),
+			(int)(arcWidth * xZoom),
+			(int)(arcHeight * yZoom));
+	}
+
+	/** @see Graphics#drawString(String, int, int) */
+	public void drawString(String s, int x, int y) {
+		if (allowText)
+			graphics.drawString(s, zoomTextPoint(x, y));
+	}
+
+	/** @see Graphics#drawText(String, int, int) */
+	public void drawText(String s, int x, int y) {
+		if (allowText)
+			graphics.drawText(s, zoomTextPoint(x, y));
+	}
+
+	/**
+	 * @see Graphics#drawText(String, int, int, int)
+	 */
+	public void drawText(String s, int x, int y, int style) {
+		if (allowText)
+			graphics.drawText(s, zoomTextPoint(x, y), style);
+	}
+
+	/**
+	 * @see Graphics#drawTextLayout(TextLayout, int, int, int, int, Color, Color)
+	 */
+	public void drawTextLayout(TextLayout layout, int x, int y, int selectionStart,
+			int selectionEnd, Color selectionForeground, Color selectionBackground) {
+		TextLayout scaled = zoomTextLayout(layout);
+		graphics.drawTextLayout(scaled,
+				(int)Math.floor(x * xZoom + fractionalX),
+				(int)Math.floor(y * yZoom + fractionalY),
+				selectionStart, selectionEnd, selectionBackground, selectionForeground);
+		scaled.dispose();
+	}
+
+	/** @see Graphics#fillArc(int, int, int, int, int, int) */
+	public void fillArc(int x, int y, int w, int h, int offset, int sweep) {
+		Rectangle z = zoomFillRect(x, y, w, h);
+		if (z.isEmpty() || sweep == 0)
+			return;
+		graphics.fillArc(z, offset, sweep);
+	}
+
+	/** @see Graphics#fillGradient(int, int, int, int, boolean) */
+	public void fillGradient(int x, int y, int w, int h, boolean vertical) {
+		graphics.fillGradient(zoomFillRect(x, y, w, h), vertical);
+	}
+
+	/** @see Graphics#fillOval(int, int, int, int) */
+	public void fillOval(int x, int y, int w, int h) {
+		graphics.fillOval(zoomFillRect(x, y, w, h));
+	}
+
+	/**
+	 * @see Graphics#fillPolygon(int[])
+	 */
+	public void fillPolygon(int[] points) {
+		graphics.fillPolygon(zoomPointList(points));
+	}
+
+	/** @see Graphics#fillPolygon(PointList) */
+	public void fillPolygon(PointList points) {
+		graphics.fillPolygon(zoomPointList(points.toIntArray()));
+	}
+
+	/** @see Graphics#fillRectangle(int, int, int, int) */
+	public void fillRectangle(int x, int y, int w, int h) {
+		graphics.fillRectangle(zoomFillRect(x, y, w, h));
+	}
+
+	/** @see Graphics#fillRoundRectangle(Rectangle, int, int) */
+	public void fillRoundRectangle(Rectangle r, int arcWidth, int arcHeight) {
+		graphics.fillRoundRectangle(zoomFillRect(r.x, r.y, r.width, r.height),
+			(int)(arcWidth * xZoom),
+			(int)(arcHeight * yZoom));
+	}
+
+	/** @see Graphics#fillString(String, int, int) */
+	public void fillString(String s, int x, int y) {
+		if (allowText)
+			graphics.fillString(s, zoomTextPoint(x, y));
+	}
+
+	/** @see Graphics#fillText(String, int, int) */
+	public void fillText(String s, int x, int y) {
+		if (allowText)
+			graphics.fillText(s, zoomTextPoint(x, y));
+	}
+
+	/**
+	 * @see Graphics#getAbsoluteScale()
+	 */
+	public double getAbsoluteScale() {
+		return xZoom * graphics.getAbsoluteScale();
+	}
+
+	/**
+	 * @see Graphics#getAlpha()
+	 */
+	public int getAlpha() {
+		return graphics.getAlpha();
+	}
+
+	/**
+	 * @see Graphics#getAntialias()
+	 */
+	public int getAntialias() {
+		return graphics.getAntialias();
+	}
+
+	/** @see Graphics#getBackgroundColor() */
+	public Color getBackgroundColor() {
+		return graphics.getBackgroundColor();
+	}
+
+	Font getCachedFont(FontKey key) {
+		Font font = (Font)fontCache.get(key);
+		if (font != null)
+			return font;
+		key = new FontKey(key.font, key.height);
+		FontData data = key.font.getFontData()[0];
+		data.setHeight(key.height);
+		Font zoomedFont = createFont(data);
+		fontCache.put(key, zoomedFont);
+		return zoomedFont;
+	}
+
+	FontData getCachedFontData(Font f) {
+		FontData data = (FontData)fontDataCache.get(f);
+		if (data != null)
+			return data;
+		data = getLocalFont().getFontData()[0];
+		fontDataCache.put(f, data);
+		return data;
+	}
+
+	/** @see Graphics#getClip(Rectangle) */
+	public Rectangle getClip(Rectangle rect) {
+		graphics.getClip(rect);
+		int x = (int)(rect.x / xZoom);
+		int y = (int)(rect.y / yZoom);
+		/*
+		 * If the clip rectangle is queried, perform an inverse zoom, and take the ceiling of
+		 * the resulting double. This is necessary because forward scaling essentially performs
+		 * a floor() function. Without this, figures will think that they don't need to paint
+		 * when actually they do.
+		 */
+		rect.width = (int)Math.ceil(rect.right() / xZoom) - x;
+		rect.height = (int)Math.ceil(rect.bottom() / yZoom) - y;
+		rect.x = x;
+		rect.y = y;
+		return rect;
+	}
+
+	/**
+	 * @see Graphics#getFillRule()
+	 */
+	public int getFillRule() {
+		return graphics.getFillRule();
+	}
+
+	/** @see Graphics#getFont() */
+	public Font getFont() {
+		return getLocalFont();
+	}
+
+	/** @see Graphics#getFontMetrics() */
+	public FontMetrics getFontMetrics() {
+		return FigureUtilities.getFontMetrics(localFont);
+	}
+
+	/** @see Graphics#getForegroundColor() */
+	public Color getForegroundColor() {
+		return graphics.getForegroundColor();
+	}
+
+	/**
+	 * @see Graphics#getInterpolation()
+	 */
+	public int getInterpolation() {
+		return graphics.getInterpolation();
+	}
+
+	/**
+	 * @see Graphics#getLineCap()
+	 */
+	public int getLineCap() {
+		return graphics.getLineCap();
+	}
+
+	/**
+	 * @see Graphics#getLineJoin()
+	 */
+	public int getLineJoin() {
+		return graphics.getLineJoin();
+	}
+
+	/** @see Graphics#getLineStyle() */
+	public int getLineStyle() {
+		return graphics.getLineStyle();
+	}
+
+	/** @see Graphics#getLineWidth() */
+	public int getLineWidth() {
+		return getLocalLineWidth();
+	}
+
+	private Font getLocalFont() {
+		return localFont;
+	}
+
+	private int getLocalLineWidth() {
+		return localLineWidth;
+	}
+
+	/**
+	 * @see Graphics#getTextAntialias()
+	 */
+	public int getTextAntialias() {
+		return graphics.getTextAntialias();
+	}
+
+	/** @see Graphics#getXORMode() */
+	public boolean getXORMode() {
+		return graphics.getXORMode();
+	}
+
+	/** @see Graphics#popState() */
+	public void popState() {
+		graphics.popState();
+		stackPointer--;
+		restoreLocalState((State)stack.get(stackPointer));
+	}
+
+	/** @see Graphics#pushState() */
+	public void pushState() {
+		State s;
+		if (stack.size() > stackPointer) {
+			s = (State)stack.get(stackPointer);
+			s.setValues(xZoom, yZoom, fractionalX, fractionalY, getLocalFont(), localLineWidth);
+		} else {
+			stack.add(new State(xZoom, yZoom, fractionalX, fractionalY, getLocalFont(), 
+									localLineWidth));
+		}
+		stackPointer++;
+
+		graphics.pushState();
+	}
+
+	private void restoreLocalState(State state) {
+		this.fractionalX = state.appliedX;
+		this.fractionalY = state.appliedY;
+		setScale(state.xZoom, state.yZoom);
+		setLocalFont(state.font);
+		setLocalLineWidth(state.lineWidth);
+	}
+
+	/** @see Graphics#restoreState() */
+	public void restoreState() {
+		graphics.restoreState();
+		restoreLocalState((State)stack.get(stackPointer - 1));
+	}
+
+	public void scale( double xAmount, double yAmount ) {
+		setScale(xZoom * xAmount, yZoom* yAmount);
+		
+	}
+	
+	/** @see Graphics#scale(double) */
+	public void scale(double amount) {
+		//setScale(zoom * amount);
+		throw new RuntimeException("Operation not supported, use scale(x, y)");
+	}
+
+	/**
+	 * @see Graphics#setAlpha(int)
+	 */
+	public void setAlpha(int alpha) {
+		graphics.setAlpha(alpha);
+	}
+
+	/**
+	 * @see Graphics#setAntialias(int)
+	 */
+	public void setAntialias(int value) {
+		graphics.setAntialias(value);
+	}
+
+	/** @see Graphics#setBackgroundColor(Color) */
+	public void setBackgroundColor(Color rgb) {
+		graphics.setBackgroundColor(rgb);
+	}
+
+	/** @see Graphics#setClip(Rectangle) */
+	public void setClip(Rectangle r) {
+		graphics.setClip(zoomClipRect(r));
+	}
+
+	/**
+	 * @see Graphics#setFillRule(int)
+	 */
+	public void setFillRule(int rule) {
+		graphics.setFillRule(rule);
+	}
+
+	/** @see Graphics#setFont(Font) */
+	public void setFont(Font f) {
+		setLocalFont(f);
+	}
+
+	/** @see Graphics#setForegroundColor(Color) */
+	public void setForegroundColor(Color rgb) {
+		graphics.setForegroundColor(rgb);
+	}
+
+	/**
+	 * @see org.eclipse.draw2d.Graphics#setInterpolation(int)
+	 */
+	public void setInterpolation(int interpolation) {
+		graphics.setInterpolation(interpolation);
+	}
+
+	/**
+	 * @see Graphics#setLineCap(int)
+	 */
+	public void setLineCap(int cap) {
+		graphics.setLineCap(cap);
+	}
+
+	/**
+	 * @see Graphics#setLineDash(int[])
+	 */
+	public void setLineDash(int[] dash) {
+		graphics.setLineDash(dash);
+	}
+
+	/**
+	 * @see Graphics#setLineJoin(int)
+	 */
+	public void setLineJoin(int join) {
+		graphics.setLineJoin(join);
+	}
+
+	/** @see Graphics#setLineStyle(int) */
+	public void setLineStyle(int style) {
+		graphics.setLineStyle(style);
+	}
+
+	/** @see Graphics#setLineWidth(int) */
+	public void setLineWidth(int width) {
+		setLocalLineWidth(width);
+	}
+
+	private void setLocalFont(Font f) {
+		localFont = f;
+		graphics.setFont(zoomFont(f));
+	}
+
+	private void setLocalLineWidth(int width) {
+		localLineWidth = width;
+		graphics.setLineWidth(zoomLineWidth(width));
+	}
+
+	
+	public void setScale( double xValue, double yValue ) {
+		if ( xValue == xZoom && yValue == yZoom ) {
+			return;
+		}
+		this.xZoom = xValue;
+		this.yZoom = yValue;
+		graphics.setFont(zoomFont(getLocalFont()));
+		graphics.setLineWidth(zoomLineWidth(localLineWidth));
+	}
+	
+	void setScale(double value) {
+		throw new RuntimeException("Operation not supported, use setScale(x,y)");
+		
+		/*
+		if (zoom == value)
+			return;
+		this.zoom = value;
+		graphics.setFont(zoomFont(getLocalFont()));
+		graphics.setLineWidth(zoomLineWidth(localLineWidth));
+		*/
+	}
+
+	/**
+	 * @see Graphics#setTextAntialias(int)
+	 */
+	public void setTextAntialias(int value) {
+		graphics.setTextAntialias(value);
+	}	
+
+	/** @see Graphics#setXORMode(boolean) */
+	public void setXORMode(boolean b) {
+		graphics.setXORMode(b);
+	}
+
+	/** @see Graphics#translate(int, int) */
+	public void translate(int dx, int dy) {
+		// fractionalX/Y is the fractional part left over from previous 
+		// translates that gets lost in the integer approximation.
+		double dxFloat = dx * xZoom + fractionalX;
+		double dyFloat = dy * yZoom + fractionalY;
+		fractionalX = dxFloat - Math.floor(dxFloat);
+		fractionalY = dyFloat - Math.floor(dyFloat);
+		graphics.translate((int)Math.floor(dxFloat), (int)Math.floor(dyFloat));
+	}
+
+	private Rectangle zoomClipRect(Rectangle r) {
+		tempRECT.x = (int)(Math.floor(r.x * xZoom + fractionalX));
+		tempRECT.y = (int)(Math.floor(r.y * yZoom + fractionalY));
+		tempRECT.width = (int)(Math.ceil(((r.x + r.width) * xZoom + fractionalX))) - tempRECT.x;
+		tempRECT.height = (int)(Math.ceil(((r.y + r.height) * yZoom + fractionalY))) - tempRECT.y;
+		return tempRECT;
+	}
+
+	private Rectangle zoomFillRect(int x, int y, int w, int h) {
+		tempRECT.x = (int)(Math.floor((x * xZoom + fractionalX)));
+		tempRECT.y = (int)(Math.floor((y * yZoom + fractionalY)));
+		tempRECT.width = (int)(Math.floor(((x + w - 1) * xZoom + fractionalX))) - tempRECT.x + 1;
+		tempRECT.height = (int)(Math.floor(((y + h - 1) * yZoom + fractionalY))) - tempRECT.y + 1;
+		return tempRECT;
+	}
+
+	Font zoomFont(Font f) {
+		if (f == null)
+			f = Display.getCurrent().getSystemFont();
+		FontData data = getCachedFontData(f);
+		int zoomedFontHeight = zoomFontHeight(data.getHeight());
+		allowText = zoomedFontHeight > 0;
+		fontKey.setValues(f, zoomedFontHeight);
+		return getCachedFont(fontKey);
+	}
+
+	int zoomFontHeight(int height) {
+		if ( yZoom < MAX_TEXT_SIZE )
+			return (int)(yZoom * height);
+		else return height;
+	}
+
+	int zoomLineWidth(int w) {
+		return w;
+	}
+
+	private int[] zoomPointList(int[] points) {
+		int[] scaled = null;
+
+		// Look in cache for a integer array with the same length as 'points'
+		for (int i = 0; i < intArrayCache.length; i++) {
+			if (intArrayCache[i].length == points.length) {
+				scaled = intArrayCache[i];
+				
+				// Move this integer array up one notch in the array
+				if (i != 0) {
+					int[] temp = intArrayCache[i - 1];
+					intArrayCache[i - 1] = scaled;
+					intArrayCache[i] = temp;	
+				}
+			}
+		}
+		
+		// If no match is found, take the one that is last and resize it.
+		if (scaled == null) {
+			intArrayCache[intArrayCache.length - 1] = new int[points.length];
+			scaled = intArrayCache[intArrayCache.length - 1];
+		}
+		
+		// Scale the points
+		for (int i = 0; (i + 1) < points.length; i += 2) {
+			scaled[i] = (int)(Math.floor((points[i] * xZoom + fractionalX)));
+			scaled[i + 1] = (int)(Math.floor((points[i + 1] * yZoom + fractionalY)));
+		}
+		return scaled;
+	}	
+
+	private Rectangle zoomRect(int x, int y, int w, int h) {
+		tempRECT.x = (int)(Math.floor(x * xZoom + fractionalX));
+		tempRECT.y = (int)(Math.floor(y * yZoom + fractionalY));
+		tempRECT.width = (int)(Math.floor(((x + w) * xZoom + fractionalX))) - tempRECT.x;
+		tempRECT.height = (int)(Math.floor(((y + h) * yZoom + fractionalY))) - tempRECT.y;
+		return tempRECT;
+	}
+
+	private TextLayout zoomTextLayout(TextLayout layout) {
+		TextLayout zoomed = new TextLayout(Display.getCurrent());
+		zoomed.setText(layout.getText());
+		
+		int zoomWidth = -1;
+		
+		if (layout.getWidth() != -1)
+			zoomWidth = ((int)(layout.getWidth() * xZoom));
+			
+		if (zoomWidth < -1 || zoomWidth == 0)
+			return null;
+		
+		zoomed.setFont(zoomFont(layout.getFont()));
+		zoomed.setAlignment(layout.getAlignment());
+		zoomed.setAscent(layout.getAscent());
+		zoomed.setDescent(layout.getDescent());
+		zoomed.setOrientation(layout.getOrientation());
+		zoomed.setSegments(layout.getSegments());
+		zoomed.setSpacing(layout.getSpacing());
+		zoomed.setTabs(layout.getTabs());
+		
+		zoomed.setWidth(zoomWidth);
+		int length = layout.getText().length();
+		if (length > 0) {
+			int start = 0, offset = 1;
+			TextStyle style = null, lastStyle = layout.getStyle(0);
+			for (; offset <= length; offset++) {
+				if (offset != length
+						&& (style = layout.getStyle(offset)) == lastStyle)
+					continue;
+				int end = offset - 1;
+				
+				if (lastStyle != null) {
+					TextStyle zoomedStyle = new TextStyle(zoomFont(lastStyle.font),
+							lastStyle.foreground, lastStyle.background);
+					zoomed.setStyle(zoomedStyle, start, end);
+				}
+				lastStyle = style;
+				start = offset;
+			}
+		}
+		return zoomed;
+	}
+
+	private Point zoomTextPoint(int x, int y) {
+		if (localCache.font != localFont) {
+			//Font is different, re-calculate its height
+			FontMetrics metric = FigureUtilities.getFontMetrics(localFont); 
+			localCache.height = metric.getHeight() - metric.getDescent();
+			localCache.font = localFont;
+		}
+		if (targetCache.font != graphics.getFont()) {
+			FontMetrics metric = graphics.getFontMetrics();
+			targetCache.font = graphics.getFont();
+			targetCache.height = metric.getHeight() - metric.getDescent();
+		}
+		return new Point(((int)(Math.floor((x * xZoom) + fractionalX))),
+							(int)(Math.floor((y + localCache.height - 1) * yZoom 
+												- targetCache.height + 1 + fractionalY)));
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ZestRootEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ZestRootEditPart.java
new file mode 100644
index 0000000..b604cb7
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/gefx/ZestRootEditPart.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *     Chisel Group, University of Victoria - Adapted for XY Scaled Graphics
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.gefx;
+
+
+
+/**
+ * All root edit parts should enable this.  This allows the GEF Factory
+ * to set the top level model element with the root edit part.
+ * @author Ian Bull
+ */
+public interface ZestRootEditPart {
+	public static final String CONNECTION_FEEDBACK_LAYER = "Connection Feedback Layer"; //$NON-NLS-1$
+	
+	public void setModelRootEditPart( Object modelRootEditPart );
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/AbstractStylingModelFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/AbstractStylingModelFactory.java
new file mode 100644
index 0000000..8e892aa
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/AbstractStylingModelFactory.java
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+
+/**
+ * Base class that can be used for model factories. Offers facilities to 
+ * style the items that have been created by the factory.
+ * @author Del Myers
+ * 
+ */
+//@tag zest.bug.160367-Refreshing.fix : update the factory to use the IStylingGraphModelFactory
+public abstract class AbstractStylingModelFactory implements IStylingGraphModelFactory {
+	private StructuredViewer viewer;
+	private int connectionStyle;
+	private int nodeStyle;
+
+	/**
+	 * 
+	 */
+	public AbstractStylingModelFactory(StructuredViewer viewer) {
+		this.viewer = viewer;
+		this.connectionStyle = IZestGraphDefaults.CONNECTION_STYLE;
+		this.nodeStyle = IZestGraphDefaults.NODE_STYLE;
+	}
+	
+	public void styleConnection(IGraphModelConnection conn) {
+		//recount the source and target connections on the node.
+		//this isn't a great way to do it, because it results in
+		//an n^2 algorithm. But, if anyone can figure out a better way
+		//go ahead and try it.
+		IGraphModelNode source = conn.getSource();
+		IGraphModelNode dest = conn.getDestination();
+		LinkedList rightList = getConnectionList(source, dest);
+		
+		LinkedList leftList = null;
+		
+		if (dest != source) {
+			leftList = getConnectionList(dest, source);
+		}
+		
+		//adjust the arcs going from source to destination
+		adjustCurves(rightList);
+		//adjust the arcs going from destination to source
+		if (leftList != null)
+			adjustCurves(leftList);
+	}
+	
+	/**
+	 * Takes a list of IGraphModelConnections and adjusts the curve depths and the
+	 * bezier curves based on the number of curves in the list.
+	 * @param rightList
+	 */
+	protected void adjustCurves(List connections) {
+		int scale = 3;
+		for (int i = 0; i < connections.size(); i++) {
+			IGraphModelConnection conn = (IGraphModelConnection) connections.get(i);
+			if (conn.getSource() == conn.getDestination()) scale = 5;
+			//even if the connection isn't curved in the style, the edit part
+			//may decide that it should be curved if source and dest are equal.
+			//@tag drawing(arcs) : check here if arcs are too close when being drawn. Adjust the constant.
+			int lineWidth = conn.getLineWidth();
+			conn.setCurveDepth((i+1)*(scale+lineWidth));
+
+//			@tag zest(bug(152530-Bezier(fix))) : set the angles, etc based on the count.
+			//limit the angle to 90 degrees.
+			conn.setStartAngle(90.0 - 85.0/Math.pow(i, 1.0/9.0));
+			conn.setEndAngle(85.0/Math.pow(i, 1.0/9.0) - 90.0);
+			//limit the length to 1
+			conn.setStartLength(.75 - .25/(Math.sqrt(i)));
+			conn.setEndLength(.75 - .25/(Math.sqrt(i)));
+		}
+	}
+
+	
+	/**
+	 * @param source
+	 * @param dest
+	 * @return
+	 */
+	private LinkedList getConnectionList(IGraphModelNode source, IGraphModelNode dest) {
+		LinkedList list = new LinkedList();
+		Iterator i = source.getSourceConnections().iterator();
+		while (i.hasNext()) {
+			IGraphModelConnection c = (IGraphModelConnection) i.next();
+			if (c.getDestination() == dest) {
+				list.add(c);
+			}
+		}
+		return list;
+	}
+
+	public void styleItem(IGraphItem item) {
+		GraphItemStyler.styleItem(item, getLabelProvider());
+		if (item instanceof IGraphModelConnection) styleConnection((IGraphModelConnection) item);
+	}
+
+	public StructuredViewer getViewer() {
+		return viewer;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#getLabelProvider()
+	 */
+	public IBaseLabelProvider getLabelProvider() {
+		return viewer.getLabelProvider();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#getContentProvider()
+	 */
+	public IStructuredContentProvider getContentProvider() {
+		return (IStructuredContentProvider) viewer.getContentProvider();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#createConnection(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel, java.lang.Object, java.lang.Object, java.lang.Object)
+	 */
+	public IGraphModelConnection createConnection(GraphModel graph, Object element, Object source, Object dest) {
+		if (source == null || dest == null) return null;
+		IGraphModelConnection oldConnection = graph.getInternalConnection(element);
+		IGraphModelNode sn = graph.getInternalNode(source);
+		IGraphModelNode dn = graph.getInternalNode(dest);
+		if (oldConnection != null) {
+			if (sn != oldConnection.getSource() || dn != oldConnection.getDestination()) {
+				graph.removeConnection(oldConnection);
+			} else {
+				styleItem(oldConnection);
+				return oldConnection;
+			}
+		}
+		if (sn == null) {
+			sn = createNode(graph, source);
+		}
+		if (dn == null) {
+			dn = createNode(graph, dest);
+		}
+		GraphModelConnection c = new GraphModelConnection(graph, element, sn, dn);
+		styleItem(c);
+		graph.addConnection(element, c);
+		return c;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#createNode(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel, java.lang.Object)
+	 */
+	public IGraphModelNode createNode(GraphModel graph, Object element) {
+		IGraphModelNode node = graph.getInternalNode(element);
+		if (node == null) {
+			node = new GraphModelNode(graph, element);
+			styleItem(node);
+			graph.addNode(element, node);
+		} else {
+			styleItem(node);
+		}
+		return node;
+	}
+	
+	public void setConnectionStyle(int style) {
+		this.connectionStyle = style;
+	}
+	
+	/**
+	 * @return the connectionStyle
+	 */
+	public int getConnectionStyle() {
+		return connectionStyle;
+	}
+	
+	public void setNodeStyle(int style) {
+		this.nodeStyle = style;
+	}
+	
+	/**
+	 * @return the nodeStyle
+	 */
+	public int getNodeStyle() {
+		return nodeStyle;
+	}
+	
+	/**
+	 * Default implementation simply restyles the item, regardless of the properties.
+	 */
+	public void update(IGraphItem item) {
+		styleItem(item);		
+	}
+	
+	/**
+	 * Default implementation simply restyles the items, regardless of the properties.
+	 */
+	public void update(IGraphItem[] items) {
+		for (int i = 0; i < items.length; i++) {
+			styleItem(items[i]);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#refreshGraph(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel)
+	 */
+	public void refreshGraph(GraphModel graph) {
+		//with this kind of graph, it is just as easy and cost-effective to
+		//rebuild the whole thing.
+		
+		Map oldMap = graph.getNodesMap();
+		HashMap nodesMap = new HashMap();
+		//have to copy the Map data accross so that it doesn't get overwritten
+		for (Iterator keys = oldMap.keySet().iterator(); keys.hasNext();) {
+			Object key = keys.next();
+			nodesMap.put(key, oldMap.get(key));
+		}
+		clearGraph(graph);
+		doBuildGraph(graph);
+		//update the positions on the new nodes to match the old ones.
+		IGraphModelNode[] nodes = graph.getNodesArray();
+		//save a little time, go with the smallest list as the primary list
+		if (nodes.length < nodesMap.keySet().size()) {
+			for (int i = 0; i < nodes.length; i++) {
+				IGraphModelNode oldNode = (IGraphModelNode) nodesMap.get(nodes[i].getExternalNode());
+				if (oldNode != null) {
+					nodes[i].setPreferredLocation(oldNode.getXInLayout(), oldNode.getYInLayout());
+				}
+			}
+		} else {
+			for (Iterator i = nodesMap.keySet().iterator(); i.hasNext();) {
+				Object key = i.next();
+				IGraphModelNode node = graph.getInternalNode(key);
+				if (node != null) {
+					IGraphModelNode oldNode = (IGraphModelNode) nodesMap.get(key);
+					node.setPreferredLocation(oldNode.getXInLayout(), oldNode.getYInLayout());
+				}
+			}
+		}
+	}
+	
+	
+	
+	/**
+	 * Convenience method for clearing all the elements in the graph.
+	 * @param graph
+	 */
+	public void clearGraph(GraphModel graph) {
+		graph.clearProxies();
+		IGraphModelNode[] nodes = graph.getNodesArray();
+		for (int i = 0; i < nodes.length; i++) {
+			graph.removeNode(nodes[i]);
+		}
+	}
+	
+	/**
+	 * Builds the graph model from the viewer's content provider. There is no guarantee that the
+	 * model will be cleared before this method is called.
+	 * @param graph
+	 */
+	protected abstract void doBuildGraph(GraphModel graph);
+	
+	/**
+	 * Determines if this element should be filtered or not.
+	 * @param parent
+	 * @param element
+	 * @return
+	 */
+	protected boolean filterElement(Object parent, Object element) {
+		ViewerFilter[] filters = getViewer().getFilters();
+		for (int i = 0; i < filters.length; i++) {
+			boolean selected = filters[i].select(viewer, parent, element);
+			if ( !selected ) return true;
+		}
+		return false;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#isFiltered(java.lang.Object)
+	 */
+	protected Object[] filter(Object parent, Object[] elements) {
+		Object[] result = elements;
+		ViewerFilter[] filters = getViewer().getFilters();
+		for (int i = 0; i < filters.length; i++) {
+			result = filters[i].filter(viewer, parent, result);
+		}
+		return result;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#refresh(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel, java.lang.Object)
+	 */
+	public void refresh(GraphModel graph, Object element) {
+		refresh(graph, element, false);
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphItem.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphItem.java
new file mode 100644
index 0000000..bfcabf6
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphItem.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Provides support for property changes.  All model elements extend this class.
+ * Also extends the Item (Widget) class to be used inside a StructuredViewer.   
+ * 
+ * @author Chris Callendar
+ */
+public abstract class GraphItem extends Item implements IGraphItem  {
+	 
+	/** Delegate used to implemenent property-change-support. */
+	private transient PropertyChangeSupport pcsDelegate = new PropertyChangeSupport(this);
+	private boolean isVisible;
+	/**
+	 * @param parent
+	 * @param style
+	 */
+	public GraphItem(Widget parent) {
+		super(parent, SWT.NO_BACKGROUND);
+		isVisible = true;
+	}
+	
+	
+	
+	/** 
+	 * Attach a non-null PropertyChangeListener to this object.
+	 * @param l a non-null PropertyChangeListener instance
+	 * @throws IllegalArgumentException if the parameter is null
+	 */
+	public synchronized void addPropertyChangeListener(PropertyChangeListener l) {
+		if (l == null) {
+			throw new IllegalArgumentException();
+		}
+		pcsDelegate.addPropertyChangeListener(l);
+	}
+	
+	/** 
+	 * Remove a PropertyChangeListener from this component.
+	 * @param l a PropertyChangeListener instance
+	 */
+	public synchronized void removePropertyChangeListener(PropertyChangeListener l) {
+		if (l != null) {
+			pcsDelegate.removePropertyChangeListener(l);
+		}
+	}
+	
+	/** 
+	 * Report a property change to registered listeners (for example edit parts).
+	 * @param property the programmatic name of the property that changed
+	 * @param oldValue the old value of this property
+	 * @param newValue the new value of this property
+	 */
+	public void firePropertyChange(String property, Object oldValue, Object newValue) {
+		if (pcsDelegate.hasListeners(property)) {
+			pcsDelegate.firePropertyChange(property, oldValue, newValue);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphItem#isVisible()
+	 */
+	public boolean isVisible() {
+		return isVisible;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphItem#setVisible(boolean)
+	 */
+	public void setVisible(boolean visible) {
+		boolean old = isVisible();
+		this.isVisible = visible;
+		if (old ^ visible)
+			firePropertyChange(VISIBLE_PROP, new Boolean(old), new Boolean(visible));
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.widgets.Widget#dispose()
+	 */
+	public void dispose() {
+		//@tag zest.bug.167132-ListenerDispose : remove all listeners.
+		pcsDelegate = new PropertyChangeSupport(this);
+		super.dispose();
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphItemStyler.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphItemStyler.java
new file mode 100644
index 0000000..1459a74
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphItemStyler.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.IFontProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.mylar.zest.core.ZestException;
+import org.eclipse.mylar.zest.core.ZestPlugin;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.core.viewers.IConnectionStyleBezierExtension;
+import org.eclipse.mylar.zest.core.viewers.IConnectionStyleProvider;
+import org.eclipse.mylar.zest.core.viewers.IEntityConnectionStyleBezierExtension;
+import org.eclipse.mylar.zest.core.viewers.IEntityConnectionStyleProvider;
+import org.eclipse.mylar.zest.core.viewers.IEntityStyleProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+
+/**
+ * Helper class used to style graph elements based on graph element stylers.
+ * @author Del Myers
+ *
+ */
+//@tag bug(151327-Styles) : created to help resolve this bug
+public class GraphItemStyler {
+	public static void styleItem(IGraphItem item, final IBaseLabelProvider labelProvider) {
+		
+		if (item instanceof IGraphModelNode) {
+			IGraphModelNode node = (IGraphModelNode)item;
+			//set defaults.
+			if (node.getGraphModel().getNodeStyle() != ZestStyles.NONE) {
+				node.setNodeStyle(node.getGraphModel().getNodeStyle());
+			} else {
+				node.setNodeStyle(IZestGraphDefaults.NODE_STYLE);
+			}
+			Object entity= node.getExternalNode();
+			if (labelProvider instanceof IEntityStyleProvider) {
+				styleNode(node, (IEntityStyleProvider)labelProvider);
+			}
+			if (labelProvider instanceof IColorProvider) {
+				IColorProvider colorProvider = (IColorProvider) labelProvider;
+				node.setForegroundColor(colorProvider.getForeground(entity));
+				node.setBackgroundColor(colorProvider.getBackground(entity));
+			}
+			if (labelProvider instanceof IFontProvider) {
+				IFontProvider fontProvider = (IFontProvider) labelProvider;
+				node.setFont(fontProvider.getFont(entity));
+			}
+			if (labelProvider instanceof ILabelProvider) {
+				String text = ((ILabelProvider)labelProvider).getText(node.getExternalNode());
+				node.setText((text != null) ? text : "");
+				node.setImage(((ILabelProvider)labelProvider).getImage(node.getExternalNode()));
+			}
+		} else if (item instanceof IGraphModelConnection) {
+			IGraphModelConnection conn = (IGraphModelConnection) item;
+		
+			//set defaults
+			if (conn.getGraphModel().getConnectionStyle() != ZestStyles.NONE) {
+				int s = conn.getGraphModel().getConnectionStyle();
+				conn.setConnectionStyle(s);
+			} else {
+				conn.setConnectionStyle(IZestGraphDefaults.CONNECTION_STYLE);
+			}
+			if (labelProvider instanceof ILabelProvider) {
+				String text = ((ILabelProvider)labelProvider).getText(conn.getExternalConnection());
+				conn.setText((text != null) ? text : "");
+				conn.setImage(((ILabelProvider)labelProvider).getImage(conn.getExternalConnection()));
+			}
+			if (labelProvider instanceof IEntityConnectionStyleProvider) {
+				styleEntityConnection(conn, (IEntityConnectionStyleProvider)labelProvider);
+			} else if (labelProvider instanceof IConnectionStyleProvider) {
+				styleConnection(conn, (IConnectionStyleProvider)labelProvider);
+			}
+			int swt = getLineStyleForZestStyle(conn.getConnectionStyle());
+			conn.setLineStyle(swt);
+			
+		}
+	}
+	
+	/**
+	 * @param conn
+	 * @param provider
+	 */
+	private static void styleConnection(IGraphModelConnection conn, IConnectionStyleProvider provider) {
+		Object rel = conn.getExternalConnection();
+		Color c;
+		int style = provider.getConnectionStyle(rel);
+		if (!ZestStyles.validateConnectionStyle(style)) ZestPlugin.error(ZestException.ERROR_INVALID_STYLE);
+		if (style != ZestStyles.NONE) {
+			conn.setConnectionStyle(style);
+		}
+//		@tag bug(152530-Bezier(fix))
+		if (ZestStyles.checkStyle(conn.getConnectionStyle(), ZestStyles.CONNECTIONS_BEZIER) &&
+			provider instanceof IConnectionStyleBezierExtension) {
+			IConnectionStyleBezierExtension bezier = (IConnectionStyleBezierExtension)provider;
+			double d;
+			if (!Double.isNaN((d = bezier.getStartAngle(rel)))) conn.setStartAngle(d);
+			if (!Double.isNaN((d = bezier.getEndAngle(rel)))) conn.setEndAngle(d);
+			if (!Double.isNaN((d = bezier.getStartDistance(rel)))) conn.setStartLength(d);
+			if (!Double.isNaN((d = bezier.getEndDistance(rel)))) conn.setEndLength(d);
+		}
+		if ((c = provider.getHighlightColor(rel)) != null) conn.setHighlightColor(c);
+		if ((c = provider.getColor(rel)) != null) conn.setLineColor(c);
+		int w = -1;
+		if ((w = provider.getLineWidth(rel)) >= 0) conn.setLineWidth(w);
+	}
+
+	/**
+	 * @param conn
+	 * @param provider
+	 */
+	private static void styleEntityConnection(IGraphModelConnection conn, IEntityConnectionStyleProvider provider) {
+		Object src = conn.getSource().getExternalNode();
+		Object dest = conn.getDestination().getExternalNode();
+		Color c;
+		int style = provider.getConnectionStyle(src, dest);
+		if (!ZestStyles.validateConnectionStyle(style)) ZestPlugin.error(ZestException.ERROR_INVALID_STYLE);
+		if (style != ZestStyles.NONE) {
+			conn.setConnectionStyle(style);
+		}
+		//@tag bug(152530-Bezier(fix))
+		if (ZestStyles.checkStyle(conn.getConnectionStyle(), ZestStyles.CONNECTIONS_BEZIER) &&
+				provider instanceof IEntityConnectionStyleBezierExtension) {
+				IEntityConnectionStyleBezierExtension bezier = 
+					(IEntityConnectionStyleBezierExtension)provider;
+				double d;
+				if (!Double.isNaN((d = bezier.getStartAngle(src, dest)))) conn.setStartAngle(d);
+				if (!Double.isNaN((d = bezier.getEndAngle(src, dest)))) conn.setEndAngle(d);
+				if (!Double.isNaN((d = bezier.getStartDistance(src, dest)))) conn.setStartLength(d);
+				if (!Double.isNaN((d = bezier.getEndDistance(src, dest)))) conn.setEndLength(d);
+			}
+		if ((c = provider.getColor(src, dest))!=null) conn.setLineColor(c);
+		if ((c = provider.getHighlightColor(src, dest)) != null) conn.setHighlightColor(c);
+		int w = -1;
+		if ((w = provider.getLineWidth(src, dest)) >= 0) conn.setLineWidth(w);
+	}
+
+	/**
+	 * Styles the given node according to the properties in the style provider.
+	 * @param node the graph element to style.
+	 * @param data the element that is being styled.
+	 * @param provider the style provier.
+	 */
+	//@tag bug(151327-Styles) : resolution
+	private static void styleNode(IGraphModelNode node, IEntityStyleProvider provider) {
+		Object entity = node.getExternalNode();
+		node.setHighlightAdjacentNodes(provider.highlightAdjacentEntities(entity));
+		if (provider.highlightAdjacentEntities(entity)) {
+			Color c = provider.getAdjacentEntityHighlightColor(entity);
+			if (c != null) node.setHighlightAdjacentColor(c);
+		}
+		Color c;
+		int width = -1;
+		if ((c = provider.getBorderColor(entity)) != null) node.setBorderColor(c);
+		if ((c = provider.getBorderHighlightColor(entity)) != null) node.setBorderHighlightColor(c);
+		if ((c = provider.getHighlightColor(entity)) != null) node.setHighlightColor(c);
+		if ((c = provider.getBackgroundColour(entity)) != null) node.setBackgroundColor(c);
+		if ((c = provider.getForegroundColour(entity)) != null) node.setForegroundColor(c);
+		if ((width = provider.getBorderWidth(entity)) >= 0) node.setBorderWidth(width);
+		
+	}
+	/**
+	 * Returns the SWT line style for the given zest connection style.
+	 *
+	 */
+	public static int getLineStyleForZestStyle(int style){
+		int lineStyles = 
+			ZestStyles.CONNECTIONS_DASH_DOT |
+			ZestStyles.CONNECTIONS_DASH |
+			ZestStyles.CONNECTIONS_DOT |
+			ZestStyles.CONNECTIONS_SOLID;
+		style = style & lineStyles;
+		if (style == 0) {
+			style = ZestStyles.CONNECTIONS_SOLID;
+		}
+		switch (style) {
+			case ZestStyles.CONNECTIONS_DASH_DOT:
+				return SWT.LINE_DASHDOT;
+			case ZestStyles.CONNECTIONS_DASH:
+				return SWT.LINE_DASH;
+			case ZestStyles.CONNECTIONS_DOT:
+				return SWT.LINE_DOT;
+		}
+		return SWT.LINE_SOLID;
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModel.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModel.java
new file mode 100644
index 0000000..8f82f48
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModel.java
@@ -0,0 +1,457 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.swt.widgets.Canvas;
+
+
+/**
+ * Holds the nodes and connections for the graph.
+ * 
+ * @author Chris Callendar
+ */
+public class GraphModel extends GraphItem {
+
+	/** Property ID to use when a child is added to this diagram. */
+	public static final String NODE_ADDED_PROP = "LayoutDiagram.NodeAdded";
+	/** Property ID to use when a child is removed from this diagram. */
+	public static final String NODE_REMOVED_PROP = "LayoutDiagram.NodeRemoved";
+	/** Property ID to use when the focus (current) node has changed in the model */
+	public static final String NODE_FOCUS_PROP = "LayoutDiagram.NodeFocus";
+	/** Property ID to use when a proxy node is removed **/
+	public static final String NODE_PROXY_REMOVED_PROP = "Proxy.NodeRemoved";
+	
+	
+	private List nodes;
+	protected List connections;
+	
+	//@tag zest(bug(153466-NoNestedClientSupply(fix))) : keep proxy connections and nodes inside the model for easy access.
+	protected List proxyConnections;
+	protected List proxyNodes;
+
+	/** Maps user nodes to internal nodes */
+	private HashMap external2InternalNodeMap; 
+
+	/** Maps user connections to internal connections */
+	private HashMap external2InternalConnectionMap;
+	private int connectionStyle;
+	private int nodeStyle;
+	
+	/**
+	 * Initializes this diagram.
+	 * @param canvas	The parent widget.
+	 */
+	public GraphModel(Canvas canvas) {
+		super(canvas);
+		this.nodes = new ArrayList();
+		this.proxyNodes = new LinkedList();
+		this.proxyConnections = new LinkedList();
+		this.connectionStyle = ZestStyles.NONE;
+		this.nodeStyle = ZestStyles.NONE;
+		this.connections  = new ArrayList();
+		this.external2InternalNodeMap = new HashMap();
+		this.external2InternalConnectionMap = new HashMap();
+	}
+
+	/**
+	 * Gets a list of the GraphModelNode children objects under the root node in this diagram.
+	 * If the root node is null then all the top level nodes are returned.
+	 * @return List of GraphModelNode objects
+	 */
+	public List getNodes() {
+		return nodes;		
+	}
+	
+	/**
+	 * Converts the list of GraphModelNode objects into an array an returns it.
+	 * @return GraphModelNode[]
+	 */
+	public IGraphModelNode[] getNodesArray() {
+		IGraphModelNode[] nodesArray = new IGraphModelNode[nodes.size()];
+		nodesArray = (IGraphModelNode[])nodes.toArray(nodesArray);
+		return nodesArray;
+	}
+	
+	/**
+	 * @return the proxyConnections
+	 */
+	 //@tag zest(bug(153466-NoNestedClientSupply(fix))) : make proxies available from the model
+	public List getProxyConnections() {
+		return proxyConnections;
+	}
+	
+	/**
+	 * @return the proxyNodes
+	 */
+	  //@tag zest(bug(153466-NoNestedClientSupply(fix))) : make proxies available from the model
+	public List getProxyNodes() {
+		return proxyNodes;
+	}
+	
+	/**
+	 * Creates and reaturns a proxy node based on the given node, and adds it
+	 * to the list of proxies in the model.
+	 * @return the proxy node.
+	 * 
+	 */
+	//@tag zest(bug(153466-NoNestedClientSupply(fix))) : proxies can only be made on the model. This ensures that they are properly monitored here.
+	public NonNestedProxyNode createProxyNode(IGraphModelNode node) {
+		NonNestedProxyNode proxy = new NonNestedProxyNode(node);
+		proxyNodes.add(proxy);
+		proxy.activate();
+		return proxy;
+	}
+	/**
+	 * Creates and returns a proxy connection based on the given connection, and
+	 * the source and target endpoints. The created proxy is also added to the
+	 * list of proxies in the model. Note, only the visual elements of the
+	 * proxy connection are used for display: the given source and target nodes will
+	 * be the actual source and target nodes for the returned proxy. The reason
+	 * for this is that the source and target nodes may themselves be proxies
+	 * for the actual source and target nodes of the original connection. Some
+	 * example usages are:
+	 * <pre>
+	 * &#47;&#47;to make a proxy connection based exactly on the given connection
+	 * graphModel.createProxyConnection(conn.getSource(), conn.getDestination(), conn);
+	 * &#47;&#47;to make a proxy using a proxy node as the source, and the original node as the target:
+	 * graphModel.createProxyConnection(graphModel.createProxyNode(conn.getSource()), conn.getDestination(), conn); 
+	 * </pre>
+	 * In general, either the original source and destination nodes, or a proxy to them, should be used.
+	 * @param source the source node that this connection will be linked to. May be a proxy.
+	 * @param target the target node that this connection will be linked to. May be a proxy.
+	 * @param conn the connection to base this proxy on.
+	 * @return the proxy connection
+	 */
+	 //@tag zest(bug(153466-NoNestedClientSupply(fix))) : proxies can only be made on the model. This ensures that they are properly monitored here.
+	public ProxyConnection createProxyConnection(IGraphModelNode source, IGraphModelNode target, IGraphModelConnection conn) {
+		ProxyConnection connection = new ProxyConnection(source, target, conn);
+		proxyConnections.add(connection);
+		connection.reconnect();
+		return connection;
+	}
+	
+	/**
+	 * Removes the given proxy node from the model, if it exists. All connections
+	 * on the node will be removed as well.
+	 * @param node
+	 */
+	 //@tag zest(bug(153466-NoNestedClientSupply(fix))) : proxies can only be made on the model. This ensures that they are properly monitored here.
+	public void removeProxyNode(NonNestedProxyNode node) {
+		if (proxyNodes.contains(node)) {
+			proxyNodes.remove(node);
+			List connections = new LinkedList();
+			connections.addAll(node.getSourceConnections());
+			connections.addAll(node.getTargetConnections());
+			IGraphModelConnection[] connectionsArray = 
+				(IGraphModelConnection[])connections.toArray(new IGraphModelConnection[connections.size()]);
+			for (int i = 0; i < connectionsArray.length; i++) {
+				IGraphModelConnection conn = connectionsArray[i];
+				if (conn instanceof ProxyConnection) {
+					removeProxyConnection((ProxyConnection) conn);
+				} else {
+					removeConnection(conn);
+				}
+			}
+			node.deactivate();
+			firePropertyChange(NODE_PROXY_REMOVED_PROP, null, node);
+		}
+	}
+	
+	/**
+	 * Disconnects the given connection if it exists in the model.
+	 * @param connection the connection to disconnect.
+	 */
+	 //@tag zest(bug(153466-NoNestedClientSupply(fix))) : proxies can only be made on the model. This ensures that they are properly monitored here.
+	public void removeProxyConnection(ProxyConnection connection) {
+		if (proxyConnections.contains(connection)) {
+			proxyConnections.remove(connection);
+			connection.disconnect();
+		}
+	}
+	
+	/**
+	 * Removes all proxie nodes and connections from the model.
+	 *
+	 */
+	 //@tag zest(bug(153466-NoNestedClientSupply(fix))) : proxies can only be made on the model. This ensures that they are properly monitored here.
+	public void clearProxies() {
+		while (proxyNodes.size() > 0) {
+			removeProxyNode((NonNestedProxyNode)proxyNodes.get(0));
+		}
+		while (proxyConnections.size() > 0) {
+			removeProxyConnection((ProxyConnection) proxyConnections.get(0));
+		}
+	}
+	
+	/**
+	 * Returns the nodes map.  The key is the node data and the value
+	 * is the GraphModelNode.
+	 * @return HashMap
+	 */
+	public HashMap getNodesMap() {
+		return external2InternalNodeMap;
+	}
+	
+	/**
+	 * Returns the connection map. They key is the connection data and the value
+	 * is te GraphModelConnection
+	 * @return
+	 */
+	public HashMap getConnectionMap() {
+		return external2InternalConnectionMap;
+	}
+	
+
+	
+	/**
+	 * Sets the default connection style.
+	 * @param connection style the connection style to set
+	 * @see org.eclipse.mylar.zest.core.ZestStyles
+	 */
+	public void setConnectionStyle(int connectionStyle) {
+		this.connectionStyle = connectionStyle;
+	}
+	
+	/**
+	 * Gets the default connection style.
+	 * @return the connection style
+	 * @see org.eclipse.mylar.zest.core.ZestStyles
+	 */
+	public int getConnectionStyle() {
+		return connectionStyle;
+	}
+	
+	/**
+	 * Sets the default node style.
+	 * @param nodeStyle the node style to set
+	 * @see org.eclipse.mylar.zest.core.ZestStyles
+	 */
+	public void setNodeStyle(int nodeStyle) {
+		this.nodeStyle = nodeStyle;
+	}
+	
+	/**
+	 * Gets the default node style.
+	 * @return the node style
+	 * @see org.eclipse.mylar.zest.core.ZestStyles
+	 */
+	public int getNodeStyle() {
+		return nodeStyle;
+	}
+	
+
+	
+	/**
+	 * Gets the list of GraphModelConnection objects.
+	 * @return list of GraphModelConnection objects
+	 */
+	public List getConnections() {
+		return this.connections;
+	}
+	
+	/**
+	 * Converts the list of GraphModelConnection objects into an array and returns it.
+	 * @return GraphModelConnection[]
+	 */
+	public IGraphModelConnection[] getConnectionsArray() {
+		IGraphModelConnection[] connsArray = new IGraphModelConnection[connections.size()];
+		connsArray = (IGraphModelConnection[])connections.toArray(connsArray);
+		return connsArray;
+	}
+	
+	/**
+	 * Adds a connection to this model
+	 * @param connection
+	 */
+	public boolean addConnection( Object externalConnection, IGraphModelConnection connection ) {
+		if ((connection != null) && connections.add(connection)) {
+			external2InternalConnectionMap.put(externalConnection, connection);
+			connection.reconnect();
+			return true;
+		}
+		return false;
+	}
+	
+	/**
+	 * Gets the internal GraphModelConnection object associated with the 
+	 * given external connection object.
+	 * @param externalConnection
+	 * @return GraphModelConnection
+	 */
+	public IGraphModelConnection getInternalConnection(Object externalConnection) {
+		if (external2InternalConnectionMap.containsKey(externalConnection)) {
+			return (IGraphModelConnection)external2InternalConnectionMap.get(externalConnection);
+		}
+		return null;
+	}
+	
+	/**
+	 * Disconnects and removes the connection as well as notifying the graph listeners
+	 * that a connection has been removed.
+	 * @param connection
+	 * @return boolean if removed
+	 */
+	public boolean removeConnection(IGraphModelConnection connection) {
+		boolean removed = false;
+		if (connection != null) {
+			connection.disconnect();
+			external2InternalConnectionMap.remove(connection.getExternalConnection());
+			removed = connections.remove(connection);
+			if ( connection != null && !((GraphModelConnection) connection).isDisposed() ) {
+				((GraphModelConnection)connection).dispose();
+			}
+		}
+		return removed;
+	}
+	
+	/**
+	 * Removes the connection associated with the external connection object.
+	 * @param externalConnection
+	 * @return boolean
+	 */
+	public boolean removeConnection(Object externalConnection) {
+		IGraphModelConnection connection = (IGraphModelConnection)external2InternalConnectionMap.get(externalConnection);
+		return this.removeConnection(connection);
+	}
+	
+	/**
+	 * Adds a new node to the diagram.
+	 * @param node The node to add
+	 * @return boolean if successful.
+	 */
+	public boolean addNode(Object externalNode, IGraphModelNode node) {
+		boolean added = false;
+		if (node != null) {
+			addNodeToList(node);
+			external2InternalNodeMap.put( externalNode, node );
+			firePropertyChange(NODE_ADDED_PROP, null, node);
+			added = true;
+		}
+		return added;
+	}
+	
+	protected void addNodeToList(IGraphModelNode node) {
+		nodes.add(node);
+	}
+	
+	protected boolean removeNodeFromList(IGraphModelNode node) {
+		return nodes.remove(node);
+	}
+	
+	/**
+	 * Removes a node from this graph and disconnects all the connections.
+	 * @param node a non-null LayoutNode instance.
+	 * @return boolean If the node was removed.
+	 */
+	public boolean removeNode(IGraphModelNode node) {
+		boolean removed = false;
+		if (node != null) {
+			external2InternalNodeMap.remove( node.getExternalNode() );
+			removed = removeNodeFromList(node);
+			if (removed) {
+				// remove the source and target connections & notify the graph listeners
+				for (Iterator iter = node.getSourceConnections().iterator(); iter.hasNext();) {
+					removeConnection((IGraphModelConnection)iter.next());
+				}
+				for (Iterator iter = node.getTargetConnections().iterator(); iter.hasNext();) {
+					removeConnection((IGraphModelConnection)iter.next());
+				}
+				firePropertyChange(NODE_REMOVED_PROP, null, node);
+			}
+			if ( !((GraphModelNode)node).isDisposed() )  {
+				((GraphModelNode)node).dispose();
+			}
+		}
+		return removed;
+	}
+	
+	/**
+	 * Removes the internal node from the external node
+	 * @param externalNode The external node representation of this node
+	 * @return true if successful
+	 */
+	public boolean removeNode( Object externalNode ) {
+		IGraphModelNode node = (IGraphModelNode) external2InternalNodeMap.get( externalNode );
+		return this.removeNode(node);
+	}
+	
+	/**
+	 * Gets the internal node from the external node.
+	 * @param o The user data.
+	 * @return The internal node or null if none
+	 */
+	public IGraphModelNode getInternalNode( Object o ) {
+		if ( external2InternalNodeMap.containsKey( o ) ) {
+			return (IGraphModelNode) external2InternalNodeMap.get( o );
+		}
+		return null;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.widgets.Widget#toString()
+	 */
+	public String toString() {
+		return "GraphModel {" + nodes.size() + " nodes, " +
+			connections.size() + " connections}";
+	}
+
+	
+	
+	/**
+	 * Fires changes to all the model elements
+	 * @param property
+	 * @param oldValue
+	 * @param newValue
+	 */
+	public void fireAllPropertyChange(String property, Object oldValue, Object newValue) {
+		for ( Iterator iter = this.connections.iterator(); iter.hasNext(); ) {
+			((IGraphModelConnection) iter.next() ).firePropertyChange(property, oldValue, newValue ); 
+		}
+		
+		for ( Iterator iter = this.nodes.iterator(); iter.hasNext(); ) {
+			((IGraphModelNode) iter.next() ).firePropertyChange(property, oldValue, newValue );
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphItem#getGraphModel()
+	 */
+	public GraphModel getGraphModel() {
+		return this;
+	}
+	
+	/**
+	 * Dispose of the nodes and edges when the graph is disposed.
+	 */
+	public void dispose() {
+		for ( Iterator iter = nodes.iterator(); iter.hasNext(); ) {
+			GraphModelNode node = (GraphModelNode) iter.next();
+			if ( node != null && !node.isDisposed() ) {
+				node.dispose();
+			}
+		}
+		for ( Iterator iter = connections.iterator(); iter.hasNext(); ) {
+			GraphModelConnection connection = (GraphModelConnection) iter.next();
+			if ( connection != null && !connection.isDisposed() ) {
+				connection.dispose();
+			}
+		}
+		super.dispose();
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelConnection.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelConnection.java
new file mode 100644
index 0000000..ae8aa81
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelConnection.java
@@ -0,0 +1,641 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.HashMap;
+
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.mylar.zest.core.IZestColorConstants;
+import org.eclipse.mylar.zest.core.ZestPlugin;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.layouts.LayoutBendPoint;
+import org.eclipse.mylar.zest.layouts.LayoutEntity;
+import org.eclipse.mylar.zest.layouts.LayoutRelationship;
+import org.eclipse.mylar.zest.layouts.constraints.LayoutConstraint;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Display;
+
+
+/**
+ * This is the graph connection model which stores the source and destination nodes and the properties
+ * of this connection (color, line width etc).
+ * 
+ * @author Chris Callendar
+ */
+public class GraphModelConnection extends GraphItem implements IGraphModelConnection, LayoutRelationship {
+
+	private Font font;
+	private IGraphModelNode sourceNode;
+	private IGraphModelNode destinationNode;
+
+	private  double weight;
+	private Color color;
+	private Color highlightColor;
+	private Color foreground;
+	private int lineWidth;
+	private int lineStyle;
+	private HashMap attributes;
+	private boolean isConnected;
+	private GraphModel graphModel;
+	
+	private Object internalConnection;
+	private int connectionStyle;
+	private int curveDepth;
+	
+
+	
+	/**
+	 * For bezier curves: angle between the start point, and the line.
+	 * This may be a hint only. Future implementations of graph viewers may
+	 * adjust the actual visual representation based on the look of the graph.
+	 */
+//	@tag zest(bug(152530-Bezier(fix)))
+	private double startAngle;
+	/**
+	 * For bezier curves: angle between the end point and the line. This may
+	 * be a hint only. Future implementations of graph viewers may adjust the
+	 * actual visual representation based on the look of the graph.
+	 */
+//	@tag zest(bug(152530-Bezier(fix)))
+	private double endAngle;
+	
+	/**
+	 * For bezier curves: this is a value from 0-1 as a ratio of the length of the
+	 * line between the start point, and the control point/the length of the connection.
+	 */
+//	@tag zest(bug(152530-Bezier(fix)))
+	private double startLength;
+	
+	/**
+	 * For bezier curves: this is a value from 0-1 as a ratio of the length of the
+	 * line between the end point, and the control point/the length of the connection.
+	 */
+//	@tag zest(bug(152530-Bezier(fix)))
+	private double endLength;
+	
+	
+	/**
+	 * Visibility based on the internal visibility of the connection, and
+	 * of the nodes.
+	 */
+	private boolean trueVisibility;
+	
+	/**
+	 * The state of visibility set by the user.
+	 */
+	private boolean visible;
+	/**
+	 * Listens for when the source and target nodes change visibility. If 
+	 * a connection's node is invisible, so should the connection.
+	 * @author Del Myers
+	 *
+	 */
+	//@tag zest.bug.156528-Filters.follows : we need this support for filters.
+	private class NodeVisibilityListener implements PropertyChangeListener {
+		/* (non-Javadoc)
+		 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+		 */
+		public void propertyChange(PropertyChangeEvent evt) {
+			if (VISIBLE_PROP.equals(evt.getPropertyName())) {
+				resetVisibility();
+			}
+		}
+	}
+	
+	private NodeVisibilityListener nodeListener;
+	
+	/**
+	 * LayoutConnection constructor, initializes the nodes and the connection properties.
+	 * Defaults to bidirectional and a weighting of 0.
+	 * @param graphModel	The graph model.
+	 * @param data			The data object for this connection.
+	 * @param source		The source node.
+	 * @param destination 	The destination node.
+	 */
+	public GraphModelConnection(GraphModel graphModel, Object data, IGraphModelNode source, IGraphModelNode destination) {
+		this(graphModel, data, source, destination, true, 0);
+	}
+	
+	/**
+	 * LayoutConnection constructor, initializes the nodes and the connection properties.
+	 * @param graphModel	The graph model.
+	 * @param data			The data object for this connection.
+	 * @param source		The source node.
+	 * @param destination 	The destination node.
+	 * @param bidirection	If the connection is bidirectional.
+	 * @param weight		The connection weight.
+	 */
+	public GraphModelConnection(GraphModel graphModel, Object data, IGraphModelNode source, IGraphModelNode destination, boolean bidirection, double weight) {
+		super(graphModel);
+		this.trueVisibility = super.isVisible();
+		this.visible = this.trueVisibility;
+		ZestPlugin plugin = ZestPlugin.getDefault();
+		this.setData(data);
+		this.connectionStyle = IZestGraphDefaults.CONNECTION_STYLE;
+		this.color = plugin.getColor(IZestColorConstants.EDGE_DEFAULT);
+		this.foreground = plugin.getColor(IZestColorConstants.EDGE_DEFAULT);
+		this.highlightColor = plugin.getColor(IZestColorConstants.EDGE_HIGHLIGHT);
+		this.lineWidth = 1;
+		this.lineStyle = Graphics.LINE_SOLID;
+		setWeightInLayout(weight);
+		this.attributes = new HashMap();
+		this.isConnected = false;
+		this.graphModel = graphModel;
+		this.sourceNode = source;
+		this.destinationNode = destination;
+		//@tag removed : can cause the edit parts to be created before the model is finished. Wait until the model is fully constructed to reconnect.
+		//reconnect(source, destination);
+		this.font = Display.getDefault().getSystemFont();
+		nodeListener = new NodeVisibilityListener();
+	}
+	
+	/**
+	 * Gets the external connection object.
+	 * @return Object
+	 */
+	public Object getExternalConnection() {
+		return this.getData();
+	}
+	
+	/**
+	 * Returns a string like 'source -> destination'
+	 * @return String
+	 */
+	public String toString() {
+		String arrow = (isBidirectionalInLayout() ? " <--> " : " --> ");
+		String src = (sourceNode != null ? sourceNode.getText() : "null");
+		String dest = (destinationNode != null ? destinationNode.getText() : "null");
+		String weight = "  (weight=" + getWeightInLayout() + ")";
+		return ("GraphModelConnection: " + src + arrow + dest + weight);
+	}
+
+	/** 
+	 * Disconnect this connection from the shapes it is attached to.
+	 */
+	public void disconnect() {
+		if (isConnected) {
+			sourceNode.removePropertyChangeListener(nodeListener);
+			destinationNode.removePropertyChangeListener(nodeListener);
+			sourceNode.removeConnection(this);
+			destinationNode.removeConnection(this);
+			isConnected = false;
+		}
+	}
+	
+	/** 
+	 * Reconnect this connection. 
+	 * The connection will reconnect with the node it was previously attached to.
+	 */  
+	public void reconnect() {
+		if (!isConnected) {
+			sourceNode.addConnection(this, true);
+			destinationNode.addConnection(this, false);
+			sourceNode.addPropertyChangeListener(nodeListener);
+			destinationNode.addPropertyChangeListener(nodeListener);
+			isConnected = true;
+		}
+	}
+
+	/**
+	 * Reconnect to a different source and/or destination node.
+	 * The connection will disconnect from its current attachments and reconnect to 
+	 * the new source and destination. 
+	 * @param newSource 		a new source endpoint for this connection (non null)
+	 * @param newDestination	a new destination endpoint for this connection (non null)
+	 * @throws IllegalArgumentException if any of the paramers are null
+	 */
+	public void reconnect(IGraphModelNode newSource, IGraphModelNode newDestination) {
+		if (newSource == null || newDestination == null ) {
+			throw new IllegalArgumentException("Invalid source and/or destination nodes");
+		}
+		disconnect();
+		this.sourceNode = newSource;
+		this.destinationNode = newDestination;
+		reconnect();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.layouts.LayoutRelationship#getSourceInLayout()
+	 */
+	public LayoutEntity getSourceInLayout() {
+		return sourceNode;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.layouts.LayoutRelationship#getDestinationInLayout()
+	 */
+	public LayoutEntity getDestinationInLayout() {
+		return destinationNode;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.layouts.LayoutRelationship#isBidirectionalInLayout()
+	 */
+	public boolean isBidirectionalInLayout() {
+		return !ZestStyles.checkStyle(connectionStyle, ZestStyles.CONNECTIONS_DIRECTED);
+	}
+
+	/**
+	 * Returns the style of this connection. Valid styles are those that begin with
+	 * CONNECTION in ZestStyles.
+	 * @return the style of this connection.
+	 * @see #ZestStyles
+	 */
+	public int getConnectionStyle() {
+		return connectionStyle;
+	}
+	/**
+	 * Returns the style of this connection. Valid styles are those that begin with
+	 * CONNECTION in ZestStyles.
+	 * @return the style of this connection.
+	 * @see #ZestStyles
+	 */
+	public void setConnectionStyle(int style) {
+		this.connectionStyle = style;
+	}
+	
+	/**
+	 * Gets the weight of this connection. The weight must be in {-1, [0-1]}.
+	 * A weight of -1 means that there is no force/tension between the nodes.
+	 * A weight of 0 results in the maximum spring length being used (farthest apart).
+	 * A weight of 1 results in the minimum spring length being used (closest together).
+	 * @see org.eclipse.mylar.zest.layouts.LayoutRelationship#getWeightInLayout()
+	 * @return the weight: {-1, [0 - 1]}.
+	 */
+	public double getWeightInLayout() {
+		return weight;
+	}
+
+	/**
+	 * Gets the font for the label on this connection
+	 * @return
+	 */
+	public Font getFont() {
+		return this.font;
+	}
+	/**
+	 * Sets the font for the label on this connection.
+	 *
+	 */
+	public void setFont(Font f) {
+		this.font = f;
+	}
+	
+	/**
+	 * Sets the weight for this connection. The weight must be in {-1, [0-1]}.
+	 * A weight of -1 means that there is no force/tension between the nodes.
+	 * A weight of 0 results in the maximum spring length being used (farthest apart).
+	 * A weight of 1 results in the minimum spring length being used (closest together).
+	 * @see org.eclipse.mylar.zest.layouts.LayoutRelationship#setWeightInLayout(double)
+	 */
+	public void setWeightInLayout(double weight) {
+		if (weight < 0) {
+			this.weight = -1;
+		} else if (weight > 1) {
+			this.weight = 1;
+		} else {
+			this.weight = weight;
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.layouts.LayoutRelationship#getAttributeInLayout(java.lang.String)
+	 */
+	public Object getAttributeInLayout(String attribute) {
+		return attributes.get(attribute);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.layouts.LayoutRelationship#setAttributeInLayout(java.lang.String, java.lang.Object)
+	 */
+	public void setAttributeInLayout(String attribute, Object value) {
+		attributes.put(attribute, value);
+	}
+
+	/**
+	 * Returns the color of this connection.
+	 * @return Color
+	 */
+	public Color getLineColor() {
+		return color;
+	}
+
+	/**
+	 * Sets the highlight color.
+	 * @param color the color to use for highlighting.
+	 */
+	public void setHighlightColor(Color color) {
+		this.highlightColor = color;
+	}
+	
+	/**
+	 * @return the highlight color
+	 */
+	public Color getHighlightColor() {
+		return highlightColor;
+	}
+	/**
+	 * Perminently sets the color of this line to the given color. This will become the
+	 * color of the line when it is not highlighted. If you would like to temporarily change
+	 * the color of the line, use changeLineColor.
+	 * @param color the color to be set.
+	 * @see changeLineColor(Color color)
+	 */
+	public void setLineColor(Color color) {
+		this.foreground = color;
+		changeLineColor(foreground);
+	}
+	
+	/**
+	 * Sets the connection color.
+	 * @param color
+	 */
+	public void changeLineColor(Color color) {
+		Color old = this.color;
+		if (this.color != color) {
+			this.color = color;
+			firePropertyChange(LINECOLOR_PROP, old, color);
+		}
+	}
+
+	/**
+	 * Returns the connection line width.
+	 * @return int
+	 */
+	public int getLineWidth() {
+		return lineWidth;
+	}
+
+	/**
+	 * Sets the connection line width.
+	 * @param lineWidth 
+	 */
+	public void setLineWidth(int lineWidth) {
+		int old = this.lineWidth;
+		if (this.lineWidth != lineWidth) {
+			this.lineWidth = lineWidth;
+			firePropertyChange(LINEWIDTH_PROP, new Integer(old), new Integer(lineWidth) );
+		}
+	}
+	
+
+	/**
+	 * Returns the connection line style.
+	 * @return int
+	 */
+	public int getLineStyle() {
+		return lineStyle;
+	}
+
+	/**
+	 * Sets the connection line style.
+	 * @param lineStyle
+	 */
+	public void setLineStyle(int lineStyle) {
+		int old = this.lineStyle;
+		if (this.lineStyle != lineStyle) {
+			this.lineStyle = lineStyle;
+			firePropertyChange(LINESTYLE_PROP, new Integer(old), new Integer(lineStyle));
+		}
+	}
+	
+	/**
+	 * Gets the source node for this relationship
+	 * @return GraphModelNode
+	 */
+	public IGraphModelNode getSource() {
+		return this.sourceNode;
+	}
+	
+	/**
+	 * Gets the target node for this relationship
+	 * @return GraphModelNode
+	 */
+	public IGraphModelNode getDestination() {
+		return this.destinationNode;
+	}
+	
+	/**
+	 * Gets the internal relationship object.
+	 * @return Object
+	 */
+	public Object getLayoutInformation() {
+		return internalConnection;
+	}
+	
+	/**
+	 * Sets the internal relationship object.
+	 * @param layoutInformation
+	 */
+	public void setLayoutInformation(Object layoutInformation) {
+		this.internalConnection = layoutInformation;
+	}
+	
+	/**
+	 * Highlights this node.  Uses the default highlight color.
+	 */
+	public void highlight() {
+		changeLineColor(highlightColor);
+		firePropertyChange(HIGHLIGHT_PROP, null, null);
+	}
+	
+	/**
+	 * Unhighlights this node.  Uses the default color.
+	 */
+	public void unhighlight() {
+		changeLineColor(foreground);
+		firePropertyChange(UNHIGHLIGHT_PROP, null, null);
+	}
+	
+	/**
+	 * Gets the graph model that this connection is in
+	 * @return The graph model that this connection is contained in
+	 */
+	public GraphModel getGraphModel() {
+		return this.graphModel;
+	}
+
+
+	public void setBendPoints(LayoutBendPoint[] bendPoints) {
+		
+	}
+
+	public void clearBendPoints() {
+		
+	}
+
+	/**
+	 * Returns the curve depth for this connection. The return value is only meaningful
+	 * if the connection style has the ZestStyles.CONNECTIONS_CURVED style set.
+	 * @return the curve depth.
+	 */
+	public int getCurveDepth() {
+		return curveDepth;
+	}
+	
+	public void setCurveDepth(int curveDepth) {
+		Integer oldDepth = new Integer(this.curveDepth);
+		this.curveDepth = curveDepth;
+		firePropertyChange(CURVE_PROP, oldDepth, new Integer(curveDepth));
+	}
+
+
+	public void populateLayoutConstraint(LayoutConstraint constraint) {
+	
+	}
+
+
+	/**
+	 * Gets the end angle for bezier arcs.
+	 * 
+	 * For bezier curves: angle between the start point, and the line.
+	 * This may be a hint only. Future implementations of graph viewers may
+	 * adjust the actual visual representation based on the look of the graph.
+	 */
+//	@tag zest(bug(152530-Bezier(fix)))
+	public double getEndAngle() {
+		return endAngle;
+	}
+	
+	/**
+	 * Sets the end angle for bezier arcs.
+	 * 
+	 * For bezier curves: angle between the start point, and the line.
+	 * This may be a hint only. Future implementations of graph viewers may
+	 * adjust the actual visual representation based on the look of the graph.
+	 * 
+	 * @param endAngle the angle to set.
+	 */
+//	@tag zest(bug(152530-Bezier(fix)))
+	public void setEndAngle(double endAngle) {
+		Double oldAngle = new Double(this.endAngle);
+		this.endAngle = endAngle;
+		firePropertyChange(CURVE_PROP, oldAngle, new Double(endAngle));
+	}
+
+	/**
+	 * For bezier curves: this is a value from 0-1 as a ratio of the length of the
+	 * line between the end point, and the control point/the length of the connection.
+	 */
+//	@tag zest(bug(152530-Bezier(fix)))
+	public double getEndLength() {
+		return endLength;
+	}
+
+	/**
+	 * For bezier curves: this is a value from 0-1 as a ratio of the length of the
+	 * line between the end point, and the control point/the length of the connection.
+	 * 
+	 * @param endLength the length to set.
+	 */
+//	@tag zest(bug(152530-Bezier(fix)))
+	public void setEndLength(double endLength) {
+		Double oldLength = new Double(this.endLength);
+		this.endLength = endLength;
+		firePropertyChange(CURVE_PROP, oldLength, new Double(endLength));
+		
+	}
+
+	/**
+	 * Gets the start angle for bezier arcs.
+	 * 
+	 * For bezier curves: angle between the end point and the line. This may
+	 * be a hint only. Future implementations of graph viewers may adjust the
+	 * actual visual representation based on the look of the graph.
+	 */
+//	@tag zest(bug(152530-Bezier(fix)))
+	public double getStartAngle() {
+		return startAngle;
+	}
+
+	/**
+	 * Sets the start angle for bezier arcs.
+	 * 
+	 * For bezier curves: angle between the end point and the line. This may
+	 * be a hint only. Future implementations of graph viewers may adjust the
+	 * actual visual representation based on the look of the graph.
+	 */
+//	@tag zest(bug(152530-Bezier(fix)))
+	public void setStartAngle(double startAngle) {
+		Double oldAngle = new Double(this.startAngle);
+		this.startAngle = startAngle;
+		firePropertyChange(CURVE_PROP, oldAngle, new Double(startAngle));
+		
+	}
+
+	/**
+	 * For bezier curves: this is a value from 0-1 as a ratio of the length of the
+	 * line between the start point, and the control point/the length of the connection.
+	 */
+//	@tag zest(bug(152530-Bezier(fix)))
+	public double getStartLength() {
+		return startLength;
+	}
+
+	/**
+	 * For bezier curves: this is a value from 0-1 as a ratio of the length of the
+	 * line between the start point, and the control point/the length of the connection.
+	 * @param startLength the length to set.
+	 */
+	//@tag zest(bug(152530-Bezier(fix)))
+	public void setStartLength(double startLength) {
+		Double oldLength = new Double(this.startLength);
+		this.startLength = startLength;
+		firePropertyChange(CURVE_PROP, oldLength, new Double(startLength));
+	}
+	
+	private boolean checkVisibilityByNodes() {
+		if (!isConnected) return false;
+		boolean visible = true;
+		if (sourceNode != null) {
+			visible &= sourceNode.isVisible();
+		} else {
+			return false;
+		}
+		if (visible && destinationNode != null) {
+			visible &= destinationNode.isVisible();
+		} else {
+			return false;
+		}
+		return visible;
+	}
+	
+	private void resetVisibility() {
+		boolean parent = this.visible;
+		boolean old = isVisible();
+		boolean nodes = checkVisibilityByNodes();
+		boolean visible = parent && nodes;
+		if (visible != old) {
+			trueVisibility = visible;
+			firePropertyChange(VISIBLE_PROP, new Boolean(old), new Boolean(nodes));
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.GraphItem#setVisible(boolean)
+	 */
+	public void setVisible(boolean visible) {
+		boolean nodeVisibility = checkVisibilityByNodes();
+		boolean old = isVisible();
+		trueVisibility = visible && nodeVisibility;
+		this.visible = visible;
+		if (old != trueVisibility) {
+			firePropertyChange(VISIBLE_PROP, new Boolean(old), new Boolean(trueVisibility));
+		}
+	}
+	
+	public boolean isVisible() {
+		return trueVisibility;
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelEntityFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelEntityFactory.java
new file mode 100644
index 0000000..9bfb445
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelEntityFactory.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.mylar.zest.core.viewers.EntityConnectionData;
+import org.eclipse.mylar.zest.core.viewers.IGraphEntityContentProvider;
+import org.eclipse.swt.widgets.Canvas;
+
+
+/**
+ * 
+ * @author Ian Bull
+ */
+public class GraphModelEntityFactory extends AbstractStylingModelFactory {
+
+	
+	public GraphModelEntityFactory(StructuredViewer viewer) {
+		super(viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#createGraphModel()
+	 */
+	public GraphModel createGraphModel() {
+		GraphModel model = new GraphModel((Canvas) getViewer().getControl());
+		doBuildGraph(model);
+		return model;
+	}
+	
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.AbstractStylingModelFactory#doBuildGraph(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel)
+	 */
+	protected void doBuildGraph(GraphModel model) {
+		clearGraph(model);
+		model.setConnectionStyle(getConnectionStyle());
+		model.setNodeStyle(getNodeStyle());
+		Object inputElement = getViewer().getInput();
+		Object entities[] = getContentProvider().getElements( inputElement );
+		if ( entities == null ) return;
+		for ( int i = 0; i < entities.length; i++ ) {
+			Object data = entities[ i ];
+			if ( !filterElement(inputElement, data) )
+				createNode(model, data);
+		}
+		for ( int i=0; i < entities.length; i++ ) {
+			Object data = entities[ i ];
+			
+			// If this element is filtered, continue to the next one.
+			if ( filterElement(inputElement, data) ) continue; 
+			Object[] related = ((IGraphEntityContentProvider)getContentProvider()).getConnectedTo( data );
+			
+			if ( related != null )
+				for ( int j = 0; j < related.length; j++ ) {
+					// if the node this node is connected to is filtered, 
+					// don't display this edge
+					if ( filterElement(inputElement, related[j] ) ) continue;
+					EntityConnectionData connectionData = new EntityConnectionData(data, related[j]);
+					if ( filterElement(inputElement, connectionData) ) continue;
+					createConnection(model, connectionData, data, related[j]);
+				}
+		}	
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#refresh(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel, java.lang.Object)
+	 */
+	public void refresh(GraphModel graph, Object element, boolean refreshLabels) {
+		if (element == null) return;
+		IGraphModelNode node = graph.getInternalNode(element);
+		if (node == null) {
+			//check to make sure that the user didn't send us an edge.
+			IGraphModelConnection conn = graph.getInternalConnection(element);
+			if (conn != null) {
+				//refresh on the connected nodes.
+				refresh(graph, conn.getSource().getExternalNode(), refreshLabels);
+				refresh(graph, conn.getDestination().getExternalNode(), refreshLabels);
+				return;
+			}
+		}
+		//can only refresh on nodes in this kind of factory.
+		if (node == null) {
+			//do nothing
+			return;
+		}
+		reconnect(graph, element, refreshLabels);
+		
+		if (refreshLabels) {
+			update(node);
+			for (Iterator it = node.getSourceConnections().iterator(); it.hasNext();) {
+				update((IGraphItem) it.next());
+			}
+			for (Iterator it = node.getTargetConnections().iterator(); it.hasNext();) {
+				update((IGraphItem) it.next());
+			}
+		}
+	}
+
+
+	/**
+	 * @param graph
+	 * @param element
+	 * @param refreshLabels
+	 */
+	private void reconnect(GraphModel graph, Object element, boolean refreshLabels) {
+		IGraphModelNode node = graph.getInternalNode(element);
+		Object[] related = ((IGraphEntityContentProvider)getContentProvider()).getConnectedTo(element);
+		List connections = node.getSourceConnections();
+		LinkedList toAdd = new LinkedList();
+		LinkedList toDelete = new LinkedList();
+		LinkedList toKeep = new LinkedList();
+		HashSet oldExternalConnections = new HashSet();
+		HashSet newExternalConnections = new HashSet();
+		for (Iterator it = connections.iterator(); it.hasNext();) {
+			oldExternalConnections.add(((IGraphModelConnection)it.next()).getExternalConnection());
+		}
+		for (int i = 0; i < related.length; i++) {
+			newExternalConnections.add(new EntityConnectionData(element, related[i]));
+		}
+		for (Iterator it = oldExternalConnections.iterator(); it.hasNext();) {
+			Object next = it.next();
+			if (!newExternalConnections.contains(next)) {
+				toDelete.add(next);
+			} else {
+				toKeep.add(next);
+			}
+		}
+		for (Iterator it = newExternalConnections.iterator(); it.hasNext();) {
+			Object next = it.next();
+			if (!oldExternalConnections.contains(next)) {
+				toAdd.add(next);
+			}
+		}
+		for (Iterator it = toDelete.iterator(); it.hasNext();) {
+			graph.removeConnection(it.next());
+		}
+		toDelete.clear();
+		LinkedList newNodeList = new LinkedList();
+		for (Iterator it = toAdd.iterator(); it.hasNext();) {
+			EntityConnectionData data = (EntityConnectionData) it.next();
+			IGraphModelNode dest = graph.getInternalNode(data.dest);
+			if (dest == null) {
+				newNodeList.add(data.dest);
+			}
+			createConnection(graph, data, data.source, data.dest);
+		}
+		toAdd.clear();
+		if (refreshLabels) {
+			for (Iterator i = toKeep.iterator(); i.hasNext();) {
+				styleItem(graph.getInternalConnection(i.next()));
+			}
+		}
+		for (Iterator it = newNodeList.iterator(); it.hasNext();) {
+			//refresh the new nodes so that we get a fully-up-to-date graph.
+			refresh(graph, it.next());
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#refresh(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel, java.lang.Object, boolean)
+	 */
+	public void refresh(GraphModel graph, Object element) {
+		refresh(graph, element, false);		
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelEntityRelationshipFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelEntityRelationshipFactory.java
new file mode 100644
index 0000000..a724585
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelEntityRelationshipFactory.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.mylar.zest.core.viewers.IGraphEntityRelationshipContentProvider;
+import org.eclipse.swt.widgets.Canvas;
+
+/**
+ * A factory for the IGraphEntityRelationshipContentProvider.
+ * @author Del Myers
+ *
+ */
+//@tag bug.154580-Content.fix
+//@tag bug.160367-Refreshing.fix : updated to use new AbstractStylingModelFactory
+public class GraphModelEntityRelationshipFactory extends AbstractStylingModelFactory {
+
+	public GraphModelEntityRelationshipFactory(StructuredViewer viewer) {
+		super(viewer);
+		if (!(viewer.getContentProvider() instanceof IGraphEntityRelationshipContentProvider)) {
+			throw new IllegalArgumentException("Expected IGraphEntityRelationshipContentProvider");
+		}
+	}
+	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.AbstractStylingModelFactory#createGraphModel()
+	 */
+	public GraphModel createGraphModel() {
+		GraphModel model = new GraphModel((Canvas) getViewer().getControl());
+		doBuildGraph(model);
+		return model;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.AbstractStylingModelFactory#doBuildGraph(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel)
+	 */
+	protected void doBuildGraph(GraphModel model) {
+		clearGraph(model);
+		model.setConnectionStyle(getConnectionStyle());
+		model.setNodeStyle(getNodeStyle());
+		Object[] nodes = getContentProvider().getElements(getViewer().getInput());
+		nodes = filter(getViewer().getInput(), nodes);
+		createModelNodes(model, nodes);
+		createModelRelationships(model);
+	}
+
+	/**
+	 * Creates all the model relationships. Assumes that all of the model nodes
+	 * have been created in the graph model already. Runtime O(n^2) + O(r).
+	 * @param model the model to create the relationship on.
+	 */
+	private void createModelRelationships(GraphModel model) {
+		IGraphModelNode[] modelNodes = model.getNodesArray();
+		IGraphEntityRelationshipContentProvider content = getCastedContent();
+		for (int i = 0; i < modelNodes.length; i++) {
+			for (int j = 0; j < modelNodes.length; j++) {
+				Object[] rels = content.getRelationships(
+					modelNodes[i].getExternalNode(), 
+					modelNodes[j].getExternalNode()
+				);
+				if (rels != null) {
+					rels = filter(getViewer().getInput(), rels);
+					for (int r = 0; r < rels.length; r++) {
+						createConnection(model, rels[r], modelNodes[i].getExternalNode(), modelNodes[j].getExternalNode());
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Creates the model nodes for the given external nodes.
+	 * 
+	 * @param model
+	 *            the graph model.
+	 * @param nodes
+	 *            the external nodes.
+	 */
+	private void createModelNodes(GraphModel model, Object[] nodes) {
+		for (int i = 0; i < nodes.length; i++) {
+			createNode(model, nodes[i]);
+		}
+	}
+
+	
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#refresh(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel, java.lang.Object)
+	 */
+	public void refresh(GraphModel graph, Object element) {
+		refresh(graph, element, false);
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#refresh(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel, java.lang.Object, boolean)
+	 */
+	public void refresh(GraphModel graph, Object element, boolean updateLabels) {
+		//with this kind of graph, it is just as easy and cost-effective to
+		//rebuild the whole thing.
+		refreshGraph(graph);
+	}
+	
+	private IGraphEntityRelationshipContentProvider getCastedContent() {
+		return (IGraphEntityRelationshipContentProvider) getContentProvider();
+	}
+
+
+
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelFactory.java
new file mode 100644
index 0000000..e4eb060
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelFactory.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.mylar.zest.core.viewers.IGraphContentProvider;
+import org.eclipse.swt.widgets.Canvas;
+
+
+
+/**
+ * This factory helps make models (nodes & connections).
+ * 
+ * @author Ian Bull
+ * @author Chris Callendar
+ */
+public class GraphModelFactory extends AbstractStylingModelFactory {
+
+
+		
+	public GraphModelFactory(StructuredViewer viewer) {
+		super(viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see ca.uvic.cs.zest.internal.graphmodel.IGraphModelFactory#createModel()
+	 */
+	public GraphModel createGraphModel() {
+		GraphModel model = new GraphModel((Canvas)getViewer().getControl());
+		doBuildGraph(model);
+		return model;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.AbstractStylingModelFactory#doBuildGraph(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel)
+	 */
+	protected void doBuildGraph(GraphModel model) {
+		clearGraph(model);
+		model.setConnectionStyle(getConnectionStyle());
+		model.setNodeStyle(getNodeStyle());
+		//make the model have the same styles as the viewer
+		Object rels[] = getContentProvider().getElements(getViewer().getInput());
+		if ( rels != null ) {
+			// If rels returns null then just continue
+			// @tag zest(bug(134928(fix))) : An empty graph causes an NPE
+			for ( int i = 0; i < rels.length; i++ ) {
+				// Check the filter on the source
+				Object source = getCastedContent().getSource(rels[i]);
+				source = filterElement(getViewer().getInput(),source) ? null : source;
+				
+				// Check hte filter on the dest
+				Object dest = getCastedContent().getDestination(rels[i]);
+				dest = filterElement(getViewer().getInput(),dest) ? null : dest;
+				if (source == null) {
+					//just create the node for the destination
+					if (dest != null) createNode(model, dest);
+					continue;
+				} else if (dest == null) {
+					//just create the node for the source
+					if (source != null) createNode(model, source);
+					continue;
+				}
+				// If any of the source, dest is null or the edge is filtered, don't create the graph.
+				if ( source != null && dest != null && !filterElement(getViewer().getInput(), rels[i])) {
+					createConnection(model, rels[i], getCastedContent().getSource(rels[i]), getCastedContent().getDestination(rels[i]));
+				}
+			}
+		}
+		
+		
+	}
+
+	private IGraphContentProvider getCastedContent() {
+		return (IGraphContentProvider)getContentProvider();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#refresh(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel, java.lang.Object)
+	 */
+	public void refresh(GraphModel graph, Object element) {
+		refresh(graph, element, false);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#refresh(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel, java.lang.Object, boolean)
+	 */
+	public void refresh(GraphModel graph, Object element, boolean updateLabels) {
+		IGraphModelConnection conn = graph.getInternalConnection(element);
+		if (conn == null) {
+			//did the user send us a node? Check all of the connections on the node.
+			IGraphModelNode node = graph.getInternalNode(element);
+			if (node != null) {
+				List connections = node.getSourceConnections();
+				for (Iterator it = connections.iterator(); it.hasNext();) {
+					IGraphModelConnection c = (IGraphModelConnection) it.next();
+					refresh(graph, c.getExternalConnection(), updateLabels);
+				}
+				connections = node.getTargetConnections();
+				for (Iterator it = connections.iterator(); it.hasNext();) {
+					IGraphModelConnection c = (IGraphModelConnection) it.next();
+					refresh(graph, c.getExternalConnection(), updateLabels);
+				}
+			}
+			return;
+		}
+		Object oldSource = conn.getSource().getExternalNode();
+		Object oldDest = conn.getDestination().getExternalNode();
+		Object newSource = getCastedContent().getSource(element);
+		Object newDest = getCastedContent().getDestination(element);
+		if (!(oldSource.equals(newSource) && oldDest.equals(newDest))) {
+			IGraphModelNode internalSource = graph.getInternalNode(newSource);
+			IGraphModelNode internalDest = graph.getInternalNode(newDest);
+			if (internalSource == null) {
+				internalSource = createNode(graph, newSource);
+			} else if (updateLabels) {
+				styleItem(internalSource);	
+			}
+			if (internalDest == null) {
+				internalDest = createNode(graph, newDest);
+			} else if (updateLabels) {
+				styleItem(internalDest);
+			}
+			
+			conn.disconnect();
+			conn.reconnect(internalSource, internalDest);
+			if (updateLabels) {
+				styleItem(conn);
+			}
+		}
+		
+	}
+
+
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelNode.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelNode.java
new file mode 100644
index 0000000..2beb1cc
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/GraphModelNode.java
@@ -0,0 +1,668 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.draw2d.FigureUtilities;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.mylar.zest.core.IZestColorConstants;
+import org.eclipse.mylar.zest.core.ZestPlugin;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.layouts.constraints.LayoutConstraint;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+
+/**
+ * Simple node class which has the following properties: color, size, location, and a label.
+ * It also has a list of connections and anchors.
+ *  
+ * @author Chris Callendar
+ * @author Del Myers
+ * @author Ian Bull
+ */
+public class GraphModelNode extends GraphItem implements IGraphModelNode {
+	private int nodeStyle;
+ 
+	private List /*IGraphModelConnection*/ sourceConnections;
+	private List /*IGraphModelConnection*/ targetConnections;
+	
+	private boolean preferredLocation;
+	private Color foreColor;
+	private Color backColor;
+	private Color highlightColor;
+	private Color highlightAdjacentColor;
+	private Color unhighlightColor;
+	private Color borderColor;
+	private Color borderHighlightColor;
+	private Color borderUnhighlightColor;
+	private int borderWidth;
+	private Point currentLocation;
+	private Dimension size;
+	private Font font;
+	private boolean cacheLabel;
+
+	protected Dimension labelSize;
+	protected GraphModel graphModel;
+	
+	/** The internal node. */
+	protected Object internalNode;
+	private boolean selected;
+	private boolean highlighted;
+	
+	public GraphModelNode(GraphModel graphModel, Object externalNode) {
+		super(graphModel);
+		initModel(graphModel, externalNode);
+	}
+	
+	public GraphModelNode(GraphModel graphModel, String label, Object externalNode) {
+		super(graphModel);
+		setText(label);
+		initModel(graphModel, externalNode);
+	}
+
+	public GraphModelNode(GraphModel graphModel, Image i, Object externalNode) {
+		super(graphModel);
+		setImage(i);
+		initModel(graphModel, externalNode);
+	}
+	
+	public GraphModelNode(GraphModel graphModel, String label, Image i, Object externalNode) {
+		super(graphModel);
+		if ( label == null ) {
+			setText(this.toString());
+		}
+		else {
+			setText(label);
+		}
+		setImage(i);
+		initModel(graphModel, externalNode);
+	}
+	
+	protected void initModel(GraphModel graphModel, Object externalNode) {		
+		this.setData(externalNode);
+		ZestPlugin plugin = ZestPlugin.getDefault();
+		this.sourceConnections = new ArrayList();
+		this.targetConnections = new ArrayList();
+		this.preferredLocation = false;		
+		this.foreColor = plugin.getColor(IZestColorConstants.BLACK);
+		this.backColor = plugin.getColor(IZestColorConstants.LIGHT_BLUE);
+		this.highlightColor = plugin.getColor(IZestColorConstants.YELLOW);
+		this.unhighlightColor = this.backColor;
+		this.highlightAdjacentColor = plugin.getColor(IZestColorConstants.ORANGE);
+		this.nodeStyle = IZestGraphDefaults.NODE_STYLE;
+		this.borderColor = plugin.getColor(IZestColorConstants.BLACK);
+		this.borderHighlightColor = plugin.getColor(IZestColorConstants.BLUE);
+		this.borderUnhighlightColor = plugin.getColor(IZestColorConstants.BLACK);
+		this.borderWidth = 1;
+		this.currentLocation = new Point(10, 10);
+		this.size = new Dimension(20, 20);
+		this.font = Display.getDefault().getSystemFont();
+		this.graphModel = graphModel;
+		
+		if (font == null) {
+			font = JFaceResources.getDefaultFont();
+		}
+	}
+	
+	/**
+	 * A simple toString that we can use for debugging
+	 */
+	public String toString() {
+		return "GraphModelNode: " + getText();
+	}
+
+	/**
+	 * Compares two nodes.
+	 */
+	public int compareTo(Object otherNode) {
+		int rv = 0;
+		if (otherNode instanceof IGraphModelNode) {
+			IGraphModelNode node = (IGraphModelNode)otherNode;
+			if (this.getText() != null) {
+				rv = this.getText().compareTo(node.getText());
+			}
+		}
+		return rv;
+	}
+
+	/**
+	 * Gets the user data associated with this node.
+	 * @return The user data associated with this node
+	 */
+	public Object getExternalNode() {
+		return this.getData();
+	}
+	
+	/**
+	 * Returns a new list of the source connections (GraphModelConnection objects).
+	 * @return List a new list of GraphModelConnect objects
+	 */
+	public List getSourceConnections() {
+	  	return new ArrayList(sourceConnections);
+	}
+
+	/**
+	 * Returns a new list of the target connections (GraphModelConnection objects).
+	 * @return List a new list of GraphModelConnect objects
+	 */
+	public List getTargetConnections() {
+	  	return new ArrayList(targetConnections);
+	}
+	
+
+	/**
+	 * Adds the given connection to the list of connections.
+	 * @param connection
+	 * @param source true if the given connection should be added as a source.
+	 */
+	public void addConnection(IGraphModelConnection connection, boolean source) {
+		if (connection != null) {
+			if (source) {
+				if (connection.getSource() == this) {
+					sourceConnections.add(connection);
+					firePropertyChange(SOURCE_CONNECTIONS_PROP, null, connection);
+				}
+			} else {
+				if (connection.getDestination() == this) {
+					targetConnections.add(connection);
+					firePropertyChange(TARGET_CONNECTIONS_PROP, null, connection);
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Removes the connection from the list if it exists.
+	 * @param connection
+	 * @return boolean if the connection was removed
+	 */
+	public boolean removeConnection(IGraphModelConnection connection) {
+		boolean removed = false;
+		if (connection != null) {
+			if (connection.getSource() == this) {
+				removed = sourceConnections.remove(connection);
+				if (removed) {
+					firePropertyChange(SOURCE_CONNECTIONS_PROP, null, connection);
+				}
+			}
+			//@tag zest.bug.unreported.fix : if the connection is a self-loop we have to remove from both source and target
+			if (connection.getDestination() == this) {
+				removed = targetConnections.remove(connection);
+				if (removed) {
+					firePropertyChange(TARGET_CONNECTIONS_PROP, null, connection);
+				}
+			}
+		}
+		return removed;
+	}
+	
+	public void setHasPreferredLocation( boolean preferredLocation ) {
+		this.preferredLocation = preferredLocation;
+	}
+	
+	public boolean hasPreferredLocation() {
+		return preferredLocation;
+	}
+
+	public double getXInLayout() {
+		return currentLocation.x;
+	}
+
+	public double getYInLayout() {
+		return currentLocation.y;
+	}
+	
+	/**
+	 * Returns the bounds of this node.  It is just the combination
+	 * of the location and the size.
+	 * @return Rectangle
+	 */
+	public Rectangle getBounds() {
+		return new Rectangle(getLocation(), getSize());
+	}
+	
+	/**
+	 * Returns a copy of the node's location.
+	 * @return Point
+	 */
+	public Point getLocation() {
+		return currentLocation.getCopy();
+	}
+
+	public double getWidthInLayout() {
+		return size.width;
+	}
+
+	public double getHeightInLayout() {
+		return size.height;
+	}
+	
+	public void setSelected( boolean selected ) {
+		if (selected = isSelected()) return;
+		if (selected) {
+			highlight();
+		} else {
+			unhighlight();
+		}
+		this.selected = selected;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#isSelected()
+	 */
+	public boolean isSelected() {
+		return selected;
+	}
+	
+	public void setPreferredLocation( double x, double y ) {
+		setLocation(x,y);
+	}
+	
+	
+	public void setLocation( double x, double y ) {
+		Point oldPoint = getLocation();
+		currentLocation.setLocation((int)x, (int)y);
+		firePropertyChange(LOCATION_PROP, oldPoint, currentLocation);
+	}
+	
+	
+	/**
+	 * Sets the layout location of this node
+	 */
+	public void setLocationInLayout(double x, double y) {
+		this.setLocation(x, y);
+	}
+	
+	/**
+	 * Returns a copy of the node's size.
+	 * @return Dimension
+	 */
+	public Dimension getSize() {
+		return size.getCopy();
+	}
+	
+	/**
+	 * Sets the size of this node
+	 */
+	public void setSizeInLayout(double width, double height) {
+		setSize(width, height);
+	}
+	
+	/**
+	 * Get the foreground colour for this node
+	 */
+	public Color getForegroundColor() {
+		return foreColor;
+	}
+	
+	/**
+	 * Set the foreground colour for this node
+	 */
+	public void setForegroundColor(Color c) {
+		Color old = foreColor;
+		this.foreColor = c;
+		firePropertyChange(COLOR_FG_PROP, old, c);
+	}
+	
+	/**
+	 * Get the background colour for this node
+	 */
+	public Color getBackgroundColor() {
+		return backColor;
+	}
+	
+	/**
+	 * Permantly sets the background color (unhighlighted).
+	 * For temporary color changes call #changeBackgroundColor instead.
+	 * @param c
+	 */
+	public void setBackgroundColor(Color c) {
+		unhighlightColor = c;
+		changeBackgroundColor(c);
+	}
+	
+	
+	/**
+	 * Sets the border color.
+	 * @param c the border color.
+	 */
+	public void setBorderColor(Color c) {
+		Color old = borderColor;
+		borderColor = c;
+		borderUnhighlightColor = c;
+		firePropertyChange(COLOR_BD_PROP, old, c);
+	}
+	
+	/**
+	 * Sets the highlighted border color.
+	 * @param c the highlighted border color.
+	 */
+	public void setBorderHighlightColor(Color c) {
+		this.borderHighlightColor =c;
+	}
+	
+		 
+	/**
+	 * Changes the background color and fires a property change event.
+	 * @param c
+	 */
+	public void changeBackgroundColor(Color c) {
+		Color old = backColor;
+		backColor = c;
+		firePropertyChange(COLOR_BG_PROP, old, c);
+		
+	}
+	
+	/**
+	 * Get the highlight colour for this node
+	 */
+	public Color getHighlightColor() {
+		return highlightColor;
+	}
+	
+	/**
+	 * Set the highlight colour for this node
+	 */
+	public void setHighlightColor(Color c) {
+		this.highlightColor = c;
+	}
+	
+	/**
+	 * Get the highlight adjacent colour for this node. This is the colour
+	 * that adjacent nodes will get
+	 */
+	public Color getHighlightAdjacentColor() {
+		return highlightAdjacentColor;
+	}
+	
+	/**
+	 * Set the highlight adjacent colour for this node. This is the colour
+	 * that adjacent node will get.
+	 */
+	public void setHighlightAdjacentColor(Color c) {
+		this.highlightAdjacentColor = c;
+	}	
+	/**
+	 * Highlights the node changing the background color and border color.
+	 * The source and destination connections are also highlighted,
+	 * and the adjacent nodes are highlighted too in a different color.
+	 */
+	public void highlight() {
+		if (isHighlighted()) return;
+		highlighted = true;
+		boolean fireEvent = false;
+		if (ZestStyles.checkStyle(getNodeStyle(), ZestStyles.NODES_HIGHLIGHT_ADJACENT)) {
+			fireEvent = true;
+			for (Iterator iter = sourceConnections.iterator(); iter.hasNext();) {
+				IGraphModelConnection conn = (IGraphModelConnection)iter.next();
+				conn.highlight();
+				conn.getDestination().highlightAdjacent();
+			}
+			for (Iterator iter = targetConnections.iterator(); iter.hasNext();) {
+				IGraphModelConnection conn = (IGraphModelConnection)iter.next();
+				conn.highlight();
+				conn.getSource().highlightAdjacent();
+			}
+		}
+		if (backColor != highlightColor) {
+			fireEvent = true;
+			borderColor = borderHighlightColor;
+			changeBackgroundColor(highlightColor);
+			// highlight the adjacent nodes
+			//@tag zest.bug.160367-Refreshing.fix : it was notices as a side-effect of this bug that we were never actually checking for the highlight-adjacent style. That is now fixed.
+		}
+		if (fireEvent) {
+			firePropertyChange(HIGHLIGHT_PROP, Boolean.FALSE, Boolean.TRUE);
+		}
+	}
+	
+	public boolean isHighlighted() {
+		return highlighted;
+	}
+	
+	/**
+	 * Restores the nodes original background color and border width.
+	 */
+	public void unhighlight() {
+		if (!isHighlighted()) return;
+		highlighted = false;
+		boolean fireEvent = false;
+		if (ZestStyles.checkStyle(getNodeStyle(), ZestStyles.NODES_HIGHLIGHT_ADJACENT)) {
+			fireEvent = true;
+			// unhighlight the adjacent edges
+			for (Iterator iter = sourceConnections.iterator(); iter.hasNext();) {
+				IGraphModelConnection conn = (IGraphModelConnection)iter.next();
+				conn.unhighlight();
+				conn.getDestination().unhighlight();
+			}
+			for (Iterator iter = targetConnections.iterator(); iter.hasNext();) {
+				IGraphModelConnection conn = (IGraphModelConnection)iter.next();
+				conn.unhighlight();
+				conn.getSource().unhighlight();
+			}
+		}
+		if (unhighlightColor != backColor) {
+			fireEvent = true;
+			changeBackgroundColor(unhighlightColor);
+			borderColor = borderUnhighlightColor;
+			
+		}
+		if (fireEvent) {
+			firePropertyChange(HIGHLIGHT_PROP, Boolean.TRUE, Boolean.FALSE);
+		}
+	}
+	
+	/**
+	 * Highlights this node using the adjacent highlight color.
+	 * This only does something if highlighAdjacentNodes is set to true 
+	 * and if the node isn't already highlighted.
+	 * @see #setHighlightAdjacentNodes(boolean)
+	 */
+	public void highlightAdjacent() {
+		if (isHighlightAdjacentNodes() && (backColor != highlightAdjacentColor) && (backColor != highlightColor)) {
+			borderColor = borderHighlightColor;
+			changeBackgroundColor(highlightAdjacentColor);
+			highlighted = true;
+		}
+	}
+	
+	/**
+	 * Returns if the nodes adjacent to this node will be highlighted when
+	 * this node is selected.
+	 * @return GraphModelNode
+	 */
+	public boolean isHighlightAdjacentNodes() {;
+		return ZestStyles.checkStyle(nodeStyle, ZestStyles.NODES_HIGHLIGHT_ADJACENT);
+	}
+
+	/**
+	 * Sets if the adjacent nodes to this one should be highlighted when
+	 * this node is selected.
+	 * @param highlightAdjacentNodes The highlightAdjacentNodes to set.
+	 */
+	public void setHighlightAdjacentNodes(boolean highlightAdjacentNodes) {
+		if (!highlightAdjacentNodes) {
+			this.nodeStyle |= ZestStyles.NODES_HIGHLIGHT_ADJACENT;
+			this.nodeStyle ^= ZestStyles.NODES_HIGHLIGHT_ADJACENT;
+			return;
+		}
+		this.nodeStyle |= ZestStyles.NODES_HIGHLIGHT_ADJACENT;
+	}
+	
+	public Color getBorderColor() {
+		return borderColor;
+	}
+	
+	public int getBorderWidth() {
+		return borderWidth;
+	}
+	
+	public void setBorderWidth(int width) {
+		this.borderWidth = width;
+	}
+
+	public Object getLayoutInformation() {
+		return internalNode;
+	}
+
+	public void setLayoutInformation(Object layoutInformation) {
+		this.internalNode = layoutInformation;
+	}
+
+	public Font getFont() {
+		return font;
+	}
+	
+	public void setFont(Font font) {
+		this.labelSize = null;
+		this.font = font;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.widgets.Item#setText(java.lang.String)
+	 */
+	public void setText(String string) {
+		this.labelSize = null;
+		super.setText(string);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.widgets.Item#setImage(org.eclipse.swt.graphics.Image)
+	 */
+	public void setImage(Image image) {
+		this.labelSize = null;
+		super.setImage(image);
+	}
+	
+	/**
+	 * Returns the extent of the text and the image with some padding.
+	 * @return Dimension the minimum size needed to display the text and the image
+	 */
+	public Dimension calculateMinimumLabelSize() {
+		if (labelSize == null) {
+			Dimension text = calculateTextExtents();
+			Dimension icon = calculateImageExtents();
+			labelSize = new Dimension(text.width + icon.width, Math.max(text.height, icon.height));
+			labelSize.expand(12, 6);
+		}
+		return labelSize;
+	}
+	
+	/**
+	 * Gets the minimum size for this node.  This is the minimum size of the label (text & icon)
+	 * @return Dimension
+	 */
+	public Dimension calculateMinimumSize() {
+		return calculateMinimumLabelSize();
+	}
+	
+	
+	/**
+	 * Gets the graphModel that this node is contained in
+	 * @return The graph model that this node is contained in
+	 */
+	public GraphModel getGraphModel() {
+		return this.graphModel;
+	}
+	
+	
+	private Dimension calculateTextExtents() {
+		Dimension dim = new Dimension(0, 0);
+		String text = getText();
+		if (text != null) {
+			if (font == null) {
+				font = JFaceResources.getDefaultFont();
+			}
+			dim.setSize(FigureUtilities.getTextExtents(text + "  ", font));
+		}
+		return dim;
+	}
+	
+	private Dimension calculateImageExtents() {
+		Dimension dim = new Dimension(0, 0);
+		Image image = getImage();
+		if (image != null) {
+			dim.setSize(new Dimension(image.getBounds().width + 4, image.getBounds().height));
+		}
+		return dim;
+	}
+
+
+	/**
+	 * @return the nodeStyle
+	 */
+	public int getNodeStyle() {
+		return nodeStyle;
+	}
+
+	/**
+	 * @param nodeStyle the nodeStyle to set
+	 */
+	public void setNodeStyle(int nodeStyle) {
+		this.nodeStyle = nodeStyle;
+		this.cacheLabel = ((this.nodeStyle & ZestStyles.NODES_CACHE_LABEL) > 0) ?  true :  false;
+	}
+
+	public void populateLayoutConstraint(LayoutConstraint constraint) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setSize(double, double)
+	 */
+	public void setSize(double width, double height) {
+		if ((width != size.width) || (height != size.height)) {
+			Object old = getSize();
+			size.width = (int)width;
+			size.height = (int)height;
+			firePropertyChange(SIZE_PROP, old, size);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getUnhiglightColor()
+	 */
+	public Color getUnhiglightColor() {
+		return unhighlightColor;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getBorderHighlightColor()
+	 */
+	public Color getBorderHighlightColor() {
+		return borderHighlightColor;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getBorderUnhiglightColor()
+	 */
+	public Color getBorderUnhiglightColor() {
+		return borderUnhighlightColor;
+	}
+
+	public boolean cacheLabel() {
+		return this.cacheLabel;
+	}
+
+	public void setCacheLabel(boolean cacheLabel) {
+		this.cacheLabel = cacheLabel;
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IGraphItem.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IGraphItem.java
new file mode 100644
index 0000000..0d89d57
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IGraphItem.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import java.beans.PropertyChangeListener;
+
+/**
+ * Simple base interface for graph items to allow property change support.
+ * The properties that change are dependant on the particular graph item.
+ * @author Del Myers
+ *
+ */
+//@tag bug(154259-Abstraction(fix))
+public interface IGraphItem {
+	/**
+	 * The visibility of this item has changed.
+	 */
+	public static final String VISIBLE_PROP = "GraphItem.Visible";
+	/** 
+	 * Attach a non-null PropertyChangeListener to this object.
+	 * @param l a non-null PropertyChangeListener instance
+	 * @throws IllegalArgumentException if the parameter is null
+	 */
+	public void addPropertyChangeListener(PropertyChangeListener l);
+	/** 
+	 * Remove a PropertyChangeListener from this component.
+	 * @param l a PropertyChangeListener instance
+	 */
+	public void removePropertyChangeListener(PropertyChangeListener l);
+	
+	/**
+	 * Fires the given property change to all listeners.
+	 * @param property
+	 * @param oldValue
+	 * @param newValue
+	 */
+	void firePropertyChange(String property, Object oldValue, Object newValue);
+	
+	/**
+	 * The data for this item. Normally the user's model object.
+	 * @return
+	 */
+	public Object getData();
+	
+	/**
+	 * Set the visibility of this item.
+	 * @param visible whether or not this item is visible.
+	 */
+	public void setVisible(boolean visible);
+	
+	/**
+	 * Get the visibility of this item.
+	 * @return the visibility of this item.
+	 */
+	public boolean isVisible();
+	
+	/**
+	 * Gets the graph that this item is rooted on. If this item is itself a graph, then this
+	 * is returned.
+	 * @return the parent graph.
+	 */
+	public GraphModel getGraphModel();
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IGraphModelConnection.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IGraphModelConnection.java
new file mode 100644
index 0000000..d89b530
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IGraphModelConnection.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.layouts.LayoutRelationship;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Abstraction of connections in the graph model to allow for a common
+ * interface for different types of connections.
+ * @author Del Myers
+ *
+ */
+//@tag bug(154259-Abstraction(fix))
+public interface IGraphModelConnection extends IGraphItem, LayoutRelationship {
+	//property changes for graph model connections.
+	/** The line color has changed for this connection **/
+	public static final String LINECOLOR_PROP = "LineColor";
+	//@tag unreported(EdgeHighlight) : fire property change when the edge highlight state changes.
+	/** The connection has been highlighted **/
+	public static final String HIGHLIGHT_PROP = "Highlight";
+	/** The connection has been unhighlighted **/
+	public static final String UNHIGHLIGHT_PROP = "UnHighlight";
+	/** The line width has changed **/
+	public static final String LINEWIDTH_PROP = "LineWidth";
+	/** The line style has changed **/
+	public static final String LINESTYLE_PROP = "LineStyle";
+	/** The state of whether this line is directed has changed **/
+	public static final String DIRECTED_EDGE_PROP = "DirectedEdgeStyle";
+	/** Something has changed with the curve, i.e. its depth or its bezier coordinates */
+	public static final String CURVE_PROP = "CurveChanged";
+	
+	
+	/**
+	 * Returns the representation of this connection in the user's model.
+	 * @return the representation of this connection in the user's model.
+	 */
+	Object getExternalConnection();
+	/**
+	 * Reconnects the connection to its source and destination nodes.
+	 *
+	 */
+	void reconnect();
+	/**
+	 * Reconnects this connection to the given source and destination nodes.
+	 * Sets this connection's source and destination to the given nodes.
+	 * @param source the source node.
+	 * @param dest the destination node.
+	 */
+	void reconnect(IGraphModelNode source, IGraphModelNode dest);
+	/**
+	 * Disconnects this connection.
+	 *
+	 */
+	void disconnect();
+	/**
+	 * Gets the root graph model that this connection is on.
+	 * @return
+	 */
+	GraphModel getGraphModel();
+	/**
+	 * Returns the source node.
+	 * @return the source node.
+	 */
+	IGraphModelNode getSource();
+	/**
+	 * Returns the destination node.
+	 * @return the destination node.
+	 */
+	IGraphModelNode getDestination();
+	/**
+	 * Sets the style for this connection.
+	 * @param style the style for this connection.
+	 * @see ZestStyles
+	 */
+	void setConnectionStyle(int style);
+	/**
+	 * Returns the style for this connection.
+	 * @return the style for this connection.
+	 * @see ZestStyles
+	 */
+	int getConnectionStyle();
+	/**
+	 * Sets the depth of the curve on this connection. Normally ignored unless
+	 * the style has ZestStyles.CONNECTIONS_CURVED set.
+	 * @param depth
+	 * @see ZestStyles
+	 */
+	void setCurveDepth(int depth);
+	/**
+	 * Returns the depth of the curve on this connection. Normally ignored unless
+	 * the style has ZestStyles.CONNECTIONS_CURVED set.
+	 * @return the curve depth.
+	 * @see ZestStyles
+	 */
+	int getCurveDepth();
+	/**
+	 * Returns the end angle for this connection. Used for connections that have
+	 * ZestStyles.CONNECTIONS_BEZIER set.
+	 * @return the end angle.
+	 * @see ZestStyles
+	 */
+	double getEndAngle();
+	/**
+	 * Returns the start angle for this connection. Used for connections that have
+	 * ZestStyles.CONNECTIONS_BEZIER set.
+	 * @return the start angle.
+	 * @see ZestStyles
+	 */
+	double getStartAngle();
+	/**
+	 * Returns the start length for this connection. Used for connections that have
+	 * ZestStyles.CONNECTIONS_BEZIER set.
+	 * @return the start length.
+	 * @see ZestStyles
+	 */
+	double getStartLength();
+	/**
+	 * Returns the end length for this connection. Used for connections that have
+	 * ZestStyles.CONNECTIONS_BEZIER set.
+	 * @return the end length.
+	 * @see ZestStyles
+	 */
+	double getEndLength();
+	/**
+	 * Sets the start angle for this connection. Used for connections that have
+	 * ZestStyles.CONNECTIONS_BEZIER set.
+	 * @param angle the start angle.
+	 * @see ZestStyles
+	 */
+	void setStartAngle(double angle);
+	/**
+	 * Sets the start length for this connection. Used for connections that have
+	 * ZestStyles.CONNECTIONS_BEZIER set.
+	 * @param length the start length.
+	 * @see ZestStyles
+	 */
+	void setStartLength(double length);
+	/**
+	 * Sets the end angle for this connection. Used for connections that have
+	 * ZestStyles.CONNECTIONS_BEZIER set.
+	 * @param angle the end angle.
+	 * @see ZestStyles
+	 */
+	void setEndAngle(double angle);
+	/**
+	 * Sets the end length for this connection. Used for connections that have
+	 * ZestStyles.CONNECTIONS_BEZIER set.
+	 * @param length the end length.
+	 * @see ZestStyles
+	 */
+	void setEndLength(double length);
+	/**
+	 * Returns the font for this connection.
+	 * @return the font for this connection.
+	 */
+	Font getFont();
+	/**
+	 * Sets the font for this connection.
+	 * @param font the font for this connection.
+	 */
+	void setFont(Font font);
+	/**
+	 * Returns the color that is used when this connection is highlighted.
+	 * @return the color that is used when this connection is highlighted.
+	 */
+	Color getHighlightColor();
+	/**
+	 * Sets the color that is used when this connection is highlighted.
+	 * @param color the color that is used when this connection is highlighted.
+	 */
+	void setHighlightColor(Color color);
+	/**
+	 * Returns the line color that is used for this connection.
+	 * @return the line color that is used for this connection.
+	 */
+	Color getLineColor();
+	/**
+	 * Permanently sets the line color that is used for this connection.
+	 * @param c the line color that is used for this connection.
+	 */
+	void setLineColor(Color c);
+	/**
+	 * Temporarily changes the line color that is used for this connection. Used as
+	 * an intermediary step for highlighting, and other graphical changes.
+	 * @return the line color that is used for this connection.
+	 */
+	void changeLineColor(Color c);
+	/**
+	 * Returns the line style for this connection, based on the SWT line styles.
+	 * @return the line style for this connection, based on the SWT line styles.
+	 * @see SWT.LINE_SOLID
+	 * @see SWT.LINE_DASH
+	 * @see SWT.LINE_DOT
+	 * @see SWT.LINE_DASHDOT
+	 * @see SWT.LINE_DASHDOTDOT
+	 */
+	//@tag zest(discussion) : sould this be set in the connection style instead, using custom zest styles?
+	int getLineStyle();
+	/**
+	 * Returns the line width in pixels for this connection. 
+	 */
+	int getLineWidth();
+	/**
+	 * Sets the line width in pixels for this connection.
+	 * @param width the line width.
+	 */
+	void setLineWidth(int width);
+	/**
+	 * Changes the color of this line to the highlight color.
+	 *
+	 */	
+	void highlight();
+	/**
+	 * Reverts back from the highlighted state.
+	 *
+	 */
+	void unhighlight();
+	/**
+	 * Sets the line style for this connection, based on the SWT line styles.
+	 * @param style the line style for this connection, based on the SWT line styles.
+	 * @see SWT.LINE_SOLID
+	 * @see SWT.LINE_DASH
+	 * @see SWT.LINE_DOT
+	 * @see SWT.LINE_DASHDOT
+	 * @see SWT.LINE_DASHDOTDOT
+	 */
+	//@tag zest(discussion) : sould this be set in the connection style instead, using custom zest styles?
+	void setLineStyle(int style);
+	
+	/**
+	 * Sets the image.
+	 * @param image
+	 */
+	void setImage(Image image);
+	
+	/**
+	 * Gets the image.
+	 * @return
+	 */
+	Image getImage();
+	
+	/**
+	 * Sets the text.
+	 * @param text
+	 */
+	void setText(String text);
+	/**
+	 * returns the text.
+	 * @return the text. 
+	 */
+	String getText();
+
+	/**
+	 * Sets the weight in the layout.
+	 * @param weight the weight in the layout.
+	 */
+	public void setWeightInLayout(double weight);
+	
+	/**
+	 * 
+	 * @return the wieght in the layout.
+	 */
+	public double getWeightInLayout();
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IGraphModelFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IGraphModelFactory.java
new file mode 100644
index 0000000..5e8e3c2
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IGraphModelFactory.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+/**
+ * @author Ian Bull
+ * @deprecated use {@link IStylingGraphModelFactory} instead.
+ */
+public interface IGraphModelFactory {
+
+	/**
+	 * Creates a new graph model
+	 * @return
+	 */
+	public abstract GraphModel createModel();
+
+	public abstract GraphModel createModelFromContentProvider(
+			Object inputElement, int nodeStyle, int connectionStyle);
+
+	/**
+	 * Creates a new relationship using the content provider to get the source and destination.
+	 * @param model	The graph model.
+	 * @param data	The data object for the new connection.
+	 * @param contentProvider	The content provider which will get the source and destination nodes.
+	 * @return GraphModelConnection
+	 */
+	public abstract IGraphModelConnection createRelationship(GraphModel model,
+			Object data);
+
+	/**
+	 * Creates a new relationship and adds it to the model
+	 * @param model
+	 * @param source
+	 * @param dest
+	 * @return GraphModelConnection
+	 */
+	public abstract IGraphModelConnection createRelationship(GraphModel model,
+			Object data, Object source, Object dest);
+
+	/**
+	 * Creates a new node and adds it to the model.  If the node already exists it is just returned.
+	 * @param model	The graph model
+	 * @param data	The new node's data object
+	 * @return GraphModelNode	the new or existing node
+	 */
+	public abstract IGraphModelNode createNode(GraphModel model, Object data);
+
+}
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IGraphModelNode.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IGraphModelNode.java
new file mode 100644
index 0000000..812af17
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IGraphModelNode.java
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import java.util.List;
+
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.layouts.LayoutEntity;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * An abstraction of nodes in the graph model to allow different kinds of nodes to have the
+ * same interface.
+ * @author Del Myers
+ *
+ */
+//@tag bug(154259-Abstraction(fix))
+public interface IGraphModelNode extends IGraphItem, LayoutEntity {
+	public static final String LOCATION_PROP = "GraphModelNode.Location";
+	public static final String SIZE_PROP = "GraphModelNode.Size";
+	public static final String FORCE_REDRAW = "GraphModelNode.Redraw";
+	public static final String COLOR_BG_PROP = "GraphModelNode.BGColor";
+	public static final String COLOR_FG_PROP = "GraphModelNode.FGColor";
+	public static final String COLOR_BD_PROP = "GraphModelNode.BDColor";
+	public static final String HIGHLIGHT_PROP = "GraphModelNode.Highlight";
+	public static final String SOURCE_CONNECTIONS_PROP = "GraphModelNode.SourceConn";
+	public static final String TARGET_CONNECTIONS_PROP = "GraphModelNode.TargetConn";
+	public static final String BRING_TO_FRONT = "GraphModelNode.BrintToFront";
+	
+	/**
+	 * Returns the node in the user's model.
+	 * @return the node in the user's model.
+	 */
+	Object getExternalNode();
+	/**
+	 * The background color.
+	 * @return the background color.
+	 */
+	Color getBackgroundColor();
+	
+	/**
+	 * Should the text on the labels be cached.
+	 * @return
+	 */
+	boolean cacheLabel();
+	
+	/**
+	 * Sets should the labels be cached
+	 * @param cacheLabel
+	 */
+	void setCacheLabel(boolean cacheLabel);
+	
+	/**
+	 * Returns the color that the background will return to after unhighlighting. 
+	 * @return the color that the background will return to after unhighlighting.
+	 */
+	Color getUnhiglightColor();
+	/**
+	 * The border color.
+	 * @return the border color.
+	 */
+	Color getBorderColor();
+	/**
+	 * Return the border highlight color;
+	 * @return the border highlight color.
+	 */
+	Color getBorderHighlightColor();
+	
+	/***
+	 * Return the border unhighlight color.
+	 * @return the border unhighlight color.
+	 */
+	Color getBorderUnhiglightColor();
+	/**
+	 * The border width in pixels.
+	 * @return the border width.
+	 */
+	int getBorderWidth();
+	/**
+	 * The font.
+	 * @return the font.
+	 */
+	Font getFont();
+	/**
+	 * The forground color.
+	 * @return the forground color.
+	 */
+	Color getForegroundColor();
+	/**
+	 * The root graph model.
+	 * @return the root graph model.
+	 */
+	GraphModel getGraphModel();
+	/**
+	 * The color used to highlight adjacent nodes.
+	 * @return the color used to highlight adjacent nodes.
+	 */
+	Color getHighlightAdjacentColor();
+	/**
+	 * The color used to highlight this node.
+	 * @return the color used to highlight this node.
+	 */
+	Color getHighlightColor();
+	/**
+	 * The location of the node.
+	 * @return the location of the node.
+	 */
+	Point getLocation();
+	/**
+	 * The style of the node.
+	 * @return the style of the node.
+	 * @see ZestStyles
+	 */
+	int getNodeStyle();
+	/**
+	 * The size of this node.
+	 * @return the size of this node.
+	 */
+	Dimension getSize();
+	/**
+	 * Returns a list of {@link IGraphModelConnection}s that have this node as their source.
+	 * @return a list of {@link IGraphModelConnection}s that have this node as their source.
+	 */
+	List getSourceConnections();
+	/**
+	 * Returns a list of {@link IGraphModelConnection}s that have this node as their target.
+	 * @return a list of {@link IGraphModelConnection}s that have this node as their target.
+	 */
+	List getTargetConnections();
+	/**
+	 * Highlights this node (and its adjacent nodes/connections, if applicable).
+	 *
+	 */
+	void highlight();
+	/**
+	 * Highlights the nodes adjacent to this one.
+	 *
+	 */
+	void highlightAdjacent();
+	/**
+	 * Returns true iff the style is set to highlight adjacent nodes.
+	 * @return true iff the style is set to highlight adjacent nodes.
+	 */
+	boolean isHighlightAdjacentNodes();
+	/**
+	 * Removes the given connection from this node, if it is connected to this node.
+	 * @param conn the connection to remove.
+	 * @return true iff the connection was removed.
+	 */
+	boolean removeConnection(IGraphModelConnection conn);
+	/**
+	 * Permanently sets the background color of this node.
+	 * @param c the new background color.
+	 */
+	void setBackgroundColor(Color c);
+	/**
+	 * Temporarily changes the background color of this node. Used as an intermediary
+	 * step for graphical feedback such as highlighting.
+	 * @param c the color to change to.
+	 */
+	void changeBackgroundColor(Color c);
+	/**
+	 * Sets the border color for this node.
+	 * @param c the new border color.
+	  */
+	void setBorderColor(Color c);
+	/**
+	 * Sets the color used on the border for when this node is highlighted.
+	 * @param c the new color.
+	 */
+	void setBorderHighlightColor(Color c);
+	/**
+	 * Sets the border width in pixels.
+	 * @param width the new width.
+	 */
+	void setBorderWidth(int width);
+	/**
+	 * Sets the font to be used for labels.
+	 * @param f the new font.
+	 */
+	void setFont(Font f);
+	/**
+	 * Sets the foreground color for labels.
+	 * @param c the new foreground color.
+	 */
+	void setForegroundColor(Color c);
+	/**
+	 * Sets whether or not this node has a preferred location.
+	 * @param hasPreferredLocation whether or not this node has a preferred location.
+	 */
+	void setHasPreferredLocation(boolean hasPreferredLocation);
+	/**
+	 * Returns true if this node has a preferred location.
+	 * @return true iff this node has a preferred location.
+	 */
+	public boolean hasPreferredLocation();
+	/**
+	 * Sets the color that will be used to highlight adjacent nodes.
+	 * @param c the color that will be used to highlight adjacent nodes.
+	 */
+	void setHighlightAdjacentColor(Color c);
+	/**
+	 * Sets whether or not this node should highlight its adjacent nodes/connections.
+	 * @param highlightAdjacent whether or not this node should highlight its adjacent nodes/connections.
+	 */
+	void setHighlightAdjacentNodes(boolean highlightAdjacent);
+	/**
+	 * Sets the highlight color for this node.
+	 * @param c the highlight color for this node.
+	 */
+	void setHighlightColor(Color c);
+	/**
+	 * Sets the image for this node.
+	 * @param image the image for this node.
+	 */
+	void setImage(Image image);
+	/**
+	 * Gets the image for this node.
+	 * @return the image for this node.
+	 */
+	Image getImage();
+	/**
+	 * Sets the location of this node.
+	 * @param x x location of this node.
+	 * @param y y location of this node.
+	 */
+	void setLocation(double x, double y);
+	/**
+	 * Sets the size.
+	 * @param width
+	 * @param height
+	 */
+	void setSize(double width, double height);
+	/**
+	 * Sets the node style.
+	 * @param style the node style.
+	 * @see ZestStyles
+	 */
+	void setNodeStyle(int style);
+	/**
+	 * Sets the preferred location of this node.
+	 * @param x the preferred x location.
+	 * @param y the preferred y location.
+	 */
+	void setPreferredLocation(double x, double y);
+	/**
+	 * Sets whether or not this node is selected.
+	 * @param selected whether or not this node is selected.
+	 */
+	void setSelected(boolean selected);
+	/**
+	 * Returns true if this node is selected.
+	 * @return true iff this node is selected.
+	 */
+	boolean isSelected();
+	/**
+	 * Sets the text label for this node.
+	 * @param text the text label for this node.
+	 */
+	void setText(String text);
+	/**
+	 * Unhighlights this node and its neighbors if applicable.
+	 *
+	 */
+	void unhighlight();
+	/**
+	 * Gets the text of this node.
+	 * @return
+	 */
+	String getText();
+	
+	/**
+	 * Adds the given connection to this graph node.
+	 * @param c the connection
+	 * @param source true if the connection should be added as a source, false
+	 * if it should be added as a target.
+	 */
+	void addConnection(IGraphModelConnection c, boolean source);
+	
+	Dimension calculateMinimumLabelSize();
+	
+	Dimension calculateMinimumSize();
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IStylingGraphModelFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IStylingGraphModelFactory.java
new file mode 100644
index 0000000..5f7dcbd
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IStylingGraphModelFactory.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.StructuredViewer;
+
+/**
+ * A Graph model factory that supports the structural and visual refreshing of graph elements based
+ * on the content provider and label provider in the viewer that this factory is associated with. 
+ * Model elements are created using the content provider supplied by getContentProvider(), and 
+ * styled using the label provider supplied by getLabelProvider(). By the end of creation and
+ * refreshing, the graph model elements are expected to be styled according to the given label provider,
+ * however, default styles are dependant on the particular implementation of IStylingGraphModelFactory.
+ * Unless otherwise documented, clients should expect that the implementation of IStylingGraphModelFactory
+ * adheres to the general defaults found in {@link IZestGraphDefaults}.
+ * @author Del Myers
+ */
+
+public interface IStylingGraphModelFactory {
+	/**
+	 * Returns the label provider used in this factory.
+	 * @return the label provider used in this factory.
+	 */
+	public IBaseLabelProvider getLabelProvider();
+	
+	/**
+	 * Returns the content provider used in this factory.
+	 * @return the content provider used in this factory.
+	 */
+	public IStructuredContentProvider getContentProvider();
+	
+	/**
+	 * Creates and returns the graph model from this factory based on the label provider and the
+	 * label provider returned in getContentProvider() and getLabelProvider().
+	 * @return the created graph model.
+	 */
+	public GraphModel createGraphModel();
+	
+	/**
+	 * Creates and returns a node on the given graph based on the user model data, "data", 
+	 * using the content provider returned by getContentProvider(). They node will also be styled
+	 * according to the information given by the label provider. If the node already exists in the
+	 * graph, it is restyled and returned; no new node is created.
+	 * @param graph the graph to create or retrieve the node on.
+	 * @param element the user model data to use in the node.
+	 * @return the node created or retrieved for the given graph.
+	 */
+	public IGraphModelNode createNode(GraphModel graph, Object element);
+	
+	/**
+	 * Creates and returns a connection with the given source and destination objects from the user
+	 * model. If the source and destination nodes don't exist for the given user model objects, they
+	 * are created using createNode(GraphModel, Object). If a connection already exists for the given
+	 * user data, but with different source or destinations, it is disconnected and reconnected to the
+	 * given source and destination. It is always styled according to the label provider provided
+	 * by getLabelProvider().
+	 * @param graph the graph to create or retrieve the connection on.
+	 * @param element the user model data to use in this connection.
+	 * @param source the user model data used for the source node.
+	 * @param dest the user model data used for the destination node.
+	 * @return the created or retrieved connection for the given graph.
+	 */
+	public IGraphModelConnection createConnection(GraphModel graph, Object element, Object source, Object dest);
+	
+	/**
+	 * Restyles the given graph items according to the label provider supplied by getLabelProvider().
+	 * @param items the items to update.
+	 */
+	public void update(IGraphItem[] items);
+	
+	/**
+	 * Restyles the given graph item according to the label provider supplied by getLabelProvider().
+	 * @param item the item to update.
+	 */
+	public void update(IGraphItem item);
+	
+	/**
+	 * Structurally refreshes the graph model nodes and connections associated with the given
+	 * user model element. Does nothing if the element does not currently exist in the view.
+	 * No restyling is done by default.
+	 * @param graph 
+	 * @param element the element to restructure.
+	 */
+	public void refresh(GraphModel graph, Object element);
+	
+	/**
+	 * Structurally refreshes the graph model nodes and connections associated with the given
+	 * user model element. If updateLabels is true, then the labels are updated as well.
+	 * Does nothing if the element does not currently exist in the view.
+	 * @param graph the graph to find the element on.
+	 * @param element the user model element.
+	 * @param updateLabels true if the labels should be updated as well.
+	 */
+	public void refresh(GraphModel graph, Object element, boolean updateLabels);
+	
+	/**
+	 * Structurally refreshes the entire graph.
+	 * @param graph the graph to refresh;
+	 */
+	public void refreshGraph(GraphModel graph);
+	
+	
+	/**
+	 * Returns the viewer that this factory is building the model for.
+	 * @return the viewer that this factory is building the model for.
+	 */
+	public StructuredViewer getViewer();
+
+	public void setConnectionStyle(int style);
+
+	/**
+	 * @return the connectionStyle
+	 */
+	public int getConnectionStyle();
+
+	public void setNodeStyle(int style);
+
+	/**
+	 * @return the nodeStyle
+	 */
+	public int getNodeStyle();
+	
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IZestGraphDefaults.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IZestGraphDefaults.java
new file mode 100644
index 0000000..0ddc3a7
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/IZestGraphDefaults.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import org.eclipse.mylar.zest.core.ZestStyles;
+
+/**
+ * Default Zest Style values for graphs, connections, and nodes.
+ * @author Del Myers
+ *
+ */
+public interface IZestGraphDefaults {
+	/**
+	 * Default node style.
+	 */
+	//@tag zest.bug.160367.fix :  we have to get rid of highlighting adjacent by default because there is no way of turning it off otherwise.
+	public static final int NODE_STYLE = 0; //removing highlight adjacent by default. ZestStyles.NODES_HIGHLIGHT_ADJACENT;
+	
+	/**
+	 * Default connection style.
+	 */
+	public static final int CONNECTION_STYLE = 
+		ZestStyles.CONNECTIONS_STRAIGHT | 
+		ZestStyles.CONNECTIONS_SOLID | 
+		ZestStyles.CONNECTIONS_VALIGN_MIDDLE |
+		ZestStyles.CONNECTIONS_HALIGN_CENTER;
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/NonNestedProxyNode.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/NonNestedProxyNode.java
new file mode 100644
index 0000000..e2240ba
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/NonNestedProxyNode.java
@@ -0,0 +1,662 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.draw2d.FigureUtilities;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.mylar.zest.layouts.constraints.LayoutConstraint;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * A model object that indirectly references a node. It is used at times when a
+ * graph model node needs to be virtually duplicated on the display, but not in
+ * the actual model.
+ * 
+ * Note: almost all calls are sent directly to the proxy. This means, color changes,
+ * font changes, etc. Will be forwarded to the proxy. Calls that are not forwarded
+ * are noted in the javadocs.
+ * @author Del Myers
+ *
+ */
+//@tag bug(153466-NoNestedClientSupply(fix)) : don't nest nodes in the client/supplier panes.
+//@tag bug(154259-Abstraction(fix)) : implement IGraphModelNode. 
+public class NonNestedProxyNode extends GraphItem implements IGraphModelNode {
+	private IGraphModelNode proxy;
+	private ArrayList sourceConnections;
+	private ArrayList targetConnections;
+	private ProxyListener proxyListener;
+	private Point currentLocation;
+	private Dimension currentSize;
+	private boolean preferredLocation;
+	private boolean selected;
+	private boolean highlighted;
+	private Object internalNode;
+	private Dimension labelSize;
+	
+	private class ProxyListener implements PropertyChangeListener {
+		/* (non-Javadoc)
+		 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+		 */
+		public void propertyChange(PropertyChangeEvent evt) {
+			String property = evt.getPropertyName();
+			if (
+				LOCATION_PROP.equals(property) || 
+				SIZE_PROP.equals(property) || 
+				SOURCE_CONNECTIONS_PROP.equals(property) ||
+				TARGET_CONNECTIONS_PROP.equals(property) ||
+				HIGHLIGHT_PROP.equals(property) ||
+				VISIBLE_PROP.equals(property)
+			) return;
+			firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());			
+		}
+	}
+
+	/**
+	 * Creates a new node that references the given proxy. Initial display information
+	 * will be taken from the proxy.
+	 */
+	protected NonNestedProxyNode(IGraphModelNode proxy) {
+		super(proxy.getGraphModel());
+		this.proxy = proxy;
+		setData(proxy.getExternalNode());
+		proxyListener = new ProxyListener();
+		sourceConnections = new ArrayList();
+		targetConnections = new ArrayList();
+		currentLocation = proxy.getLocation().getCopy();
+		currentSize = proxy.getSize().getCopy();
+		this.preferredLocation = proxy.hasPreferredLocation();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.widgets.Widget#getData()
+	 */
+	public Object getData() {
+		return getExternalNode();
+	}
+	
+	/**
+	 * Connects this node to its proxy to start listening for property changes on
+	 * the proxy. Any overriders must call super on this methd.
+	 *
+	 */
+	protected void activate() {
+		proxy.addPropertyChangeListener(proxyListener);
+	}
+	
+	/**
+	 * Disconnects this node from its proxy and stops listening for changes.
+	 * Any overriders must call super on this methd.
+	 *
+	 */
+	protected void deactivate() {
+		proxy.removePropertyChangeListener(proxyListener);
+	}
+	
+
+	/**
+	 * Adds the given connection to the list of connections. This is not forwarded
+	 * to the proxy. All connections must be added manually to this node
+	 * because it is impossible to infer from the model which connections should
+	 * be copied from the proxy.
+	 * @param connection
+	 * @param source true if the given connection should be added as a source.
+	 */
+	public void addConnection(IGraphModelConnection connection, boolean source) {
+		if (connection != null) {
+			if (source) {
+				if (connection.getSource() == this) {
+					sourceConnections.add(connection);
+					firePropertyChange(SOURCE_CONNECTIONS_PROP, null, connection);
+				}
+			} else {
+				if (connection.getDestination() == this) {
+					targetConnections.add(connection);
+					firePropertyChange(TARGET_CONNECTIONS_PROP, null, connection);
+				}
+			}
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#changeBackgroundColor(org.eclipse.swt.graphics.Color)
+	 */
+	public void changeBackgroundColor(Color c) {
+		proxy.changeBackgroundColor(c);		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getBackgroundColor()
+	 */
+	public Color getBackgroundColor() {
+		return proxy.getBackgroundColor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getBorderColor()
+	 */
+	public Color getBorderColor() {
+		return proxy.getBorderColor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getBorderWidth()
+	 */
+	public int getBorderWidth() {
+		return proxy.getBorderWidth();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getExternalNode()
+	 */
+	public Object getExternalNode() {
+		return proxy.getExternalNode();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getFont()
+	 */
+	public Font getFont() {
+		return proxy.getFont();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getForegroundColor()
+	 */
+	public Color getForegroundColor() {
+		return proxy.getForegroundColor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getGraphModel()
+	 */
+	public GraphModel getGraphModel() {
+		return proxy.getGraphModel();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getHighlightAdjacentColor()
+	 */
+	public Color getHighlightAdjacentColor() {
+		return proxy.getHighlightAdjacentColor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getHighlightColor()
+	 */
+	public Color getHighlightColor() {
+		return proxy.getHighlightColor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getImage()
+	 */
+	public Image getImage() {
+		return proxy.getImage();
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 */
+	public Point getLocation() {
+		return currentLocation.getCopy();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getNodeStyle()
+	 */
+	public int getNodeStyle() {
+		return proxy.getNodeStyle();
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getSize()
+	 */
+	public Dimension getSize() {
+		return currentSize.getCopy();
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getSourceConnections()
+	 */
+	public List getSourceConnections() {
+		return sourceConnections;
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getTargetConnections()
+	 */
+	public List getTargetConnections() {
+		return targetConnections;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getText()
+	 */
+	public String getText() {
+		return proxy.getText();
+	}
+
+	/**
+	 * Highlights the node changing the background color and border color.
+	 * The source and destination connections are also highlighted,
+	 * and the adjacent nodes are highlighted too in a different color.
+	 */
+	public void highlight() {
+		if (isHighlighted()) return;
+		changeBackgroundColor(getHighlightColor());
+		// highlight the adjacent nodes
+		for (Iterator iter = sourceConnections.iterator(); iter.hasNext();) {
+			IGraphModelConnection conn = (IGraphModelConnection)iter.next();
+			conn.highlight();
+			conn.getDestination().highlightAdjacent();
+		}
+		for (Iterator iter = targetConnections.iterator(); iter.hasNext();) {
+			IGraphModelConnection conn = (IGraphModelConnection)iter.next();
+			conn.highlight();
+			conn.getSource().highlightAdjacent();
+		}
+		highlighted = true;
+		firePropertyChange(HIGHLIGHT_PROP, Boolean.FALSE, Boolean.TRUE);
+
+	}
+	
+	public boolean isHighlighted() {
+		return highlighted;
+	}
+	
+	/**
+	 * Restores the nodes original background color and border width.
+	 */
+	public void unhighlight() {
+		if (!isHighlighted()) return;
+		changeBackgroundColor(getUnhiglightColor());
+		// unhighlight the adjacent edges
+		for (Iterator iter = sourceConnections.iterator(); iter.hasNext();) {
+			IGraphModelConnection conn = (IGraphModelConnection)iter.next();
+			conn.unhighlight();
+			conn.getDestination().unhighlight();
+		}
+		for (Iterator iter = targetConnections.iterator(); iter.hasNext();) {
+			IGraphModelConnection conn = (IGraphModelConnection)iter.next();
+			conn.unhighlight();
+			conn.getSource().unhighlight();
+		}
+		highlighted = false;
+		firePropertyChange(HIGHLIGHT_PROP, Boolean.TRUE, Boolean.FALSE);
+	
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#highlightAdjacent()
+	 */
+	public void highlightAdjacent() {
+		proxy.highlightAdjacent();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#isHighlightAdjacentNodes()
+	 */
+	public boolean isHighlightAdjacentNodes() {
+		return proxy.isHighlightAdjacentNodes();
+	}
+
+	/**
+	 * Not forwarded to the proxy
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#removeConnection(org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelConnection)
+	 */
+	public boolean removeConnection(IGraphModelConnection connection) {
+		boolean removed = false;
+		if (connection != null) {
+			if (connection.getSource() == this) {
+				removed = sourceConnections.remove(connection);
+				if (removed) {
+					firePropertyChange(SOURCE_CONNECTIONS_PROP, null, connection);
+				}
+			}
+			if (connection.getDestination() == this) {
+				removed = targetConnections.remove(connection);
+				if (removed) {
+					firePropertyChange(TARGET_CONNECTIONS_PROP, null, connection);
+				}
+			}
+		}
+		return removed;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setBackgroundColor(org.eclipse.swt.graphics.Color)
+	 */
+	public void setBackgroundColor(Color c) {
+		proxy.setBackgroundColor(c);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setBorderColor(org.eclipse.swt.graphics.Color)
+	 */
+	public void setBorderColor(Color c) {
+		proxy.setBorderColor(c);		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setBorderHighlightColor(org.eclipse.swt.graphics.Color)
+	 */
+	public void setBorderHighlightColor(Color c) {
+		proxy.setBorderHighlightColor(c);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setBorderWidth(int)
+	 */
+	public void setBorderWidth(int width) {
+		proxy.setBorderWidth(width);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setFont(org.eclipse.swt.graphics.Font)
+	 */
+	public void setFont(Font f) {
+		proxy.setFont(f);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setForegroundColor(org.eclipse.swt.graphics.Color)
+	 */
+	public void setForegroundColor(Color c) {
+		proxy.setForegroundColor(c);
+	}
+
+	/**
+	 * Not forarded to the proxy.
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setHasPreferredLocation(boolean)
+	 */
+	public void setHasPreferredLocation(boolean hasPreferredLocation) {
+		this.preferredLocation = hasPreferredLocation;
+	}
+	
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#hasPreferredLocation()
+	 */
+	public boolean hasPreferredLocation() {
+		return preferredLocation;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setHighlightAdjacentColor(org.eclipse.swt.graphics.Color)
+	 */
+	public void setHighlightAdjacentColor(Color c) {
+		proxy.setHighlightAdjacentColor(c);		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setHighlightAdjacentNodes(boolean)
+	 */
+	public void setHighlightAdjacentNodes(boolean highlightAdjacent) {
+		proxy.setHighlightAdjacentNodes(highlightAdjacent);		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setHighlightColor(org.eclipse.swt.graphics.Color)
+	 */
+	public void setHighlightColor(Color c) {
+		proxy.setHighlightColor(c);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setImage(org.eclipse.swt.graphics.Image)
+	 */
+	public void setImage(Image image) {
+		proxy.setImage(image);
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setLocation(double, double)
+	 */
+	public void setLocation( double x, double y ) {
+		Point oldPoint = getLocation();
+		currentLocation.setLocation((int)x, (int)y);
+		firePropertyChange(LOCATION_PROP, oldPoint, currentLocation);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setNodeStyle(int)
+	 */
+	public void setNodeStyle(int style) {
+		proxy.setNodeStyle(style);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setPreferredLocation(double, double)
+	 */
+	public void setPreferredLocation(double x, double y) {
+		setLocation(x,y);
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setSelected(boolean)
+	 */
+	public void setSelected( boolean selected ) {
+		if (selected = isSelected()) return;
+		if (selected) {
+			highlight();
+		} else {
+			unhighlight();
+		}
+		this.selected = selected;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#isSelected()
+	 */
+	public boolean isSelected() {
+		return selected;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setText(java.lang.String)
+	 */
+	public void setText(String text) {
+		proxy.setText(text);
+	}
+
+	
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.layouts.LayoutEntity#getHeightInLayout()
+	 */
+	public double getHeightInLayout() {
+		return getSize().height;
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.layouts.LayoutEntity#getLayoutInformation()
+	 */
+	public Object getLayoutInformation() {
+		return internalNode;
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.layouts.LayoutEntity#getWidthInLayout()
+	 */
+	public double getWidthInLayout() {
+		return getSize().width;
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.layouts.LayoutEntity#getXInLayout()
+	 */
+	public double getXInLayout() {
+		return getLocation().x;
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.layouts.LayoutEntity#getYInLayout()
+	 */
+	public double getYInLayout() {
+		return getLocation().y;
+	}
+
+	/**
+	 * Does nothing.
+	 * @see org.eclipse.mylar.zest.layouts.LayoutEntity#populateLayoutConstraint(org.eclipse.mylar.zest.layouts.constraints.LayoutConstraint)
+	 */
+	public void populateLayoutConstraint(LayoutConstraint constraint) {
+	
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.layouts.LayoutEntity#setLayoutInformation(java.lang.Object)
+	 */
+	public void setLayoutInformation(Object internalEntity) {
+		this.internalNode = internalEntity;
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.layouts.LayoutEntity#setLocationInLayout(double, double)
+	 */
+	public void setLocationInLayout(double x, double y) {
+		setLocation(x, y);
+	}
+
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.layouts.LayoutEntity#setSizeInLayout(double, double)
+	 */
+	public void setSizeInLayout(double width, double height) {
+		setSize(width, height);
+	}
+	
+	/**
+	 * Not forwarded to the proxy.
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setSize(double, double)
+	 */
+	public void setSize(double width, double height) {
+		Object old = getSize();
+		currentSize.setSize(new Dimension((int)width, (int)height));
+		firePropertyChange(SIZE_PROP, old, currentSize);
+	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.Comparable#compareTo(java.lang.Object)
+	 */
+	public int compareTo(Object otherNode) {
+		int rv = 0;
+		if (otherNode instanceof IGraphModelNode) {
+			IGraphModelNode node = (IGraphModelNode)otherNode;
+			if (this.getText() != null) {
+				rv = this.getText().compareTo(node.getText());
+			}
+		}
+		return rv;
+	}
+	
+	
+	public IGraphModelNode getProxy() {
+		return proxy;
+	}
+	
+	/**
+	 * Returns the extent of the text and the image with some padding.
+	 * @return Dimension the minimum size needed to display the text and the image
+	 */
+	public Dimension calculateMinimumLabelSize() {
+		if (labelSize == null) {
+			Dimension text = calculateTextExtents();
+			Dimension icon = calculateImageExtents();
+			labelSize = new Dimension(text.width + icon.width, Math.max(text.height, icon.height));
+			labelSize.expand(12, 6);
+		}
+		return labelSize;
+	}
+	
+	private Dimension calculateTextExtents() {
+		Dimension dim = new Dimension(0, 0);
+		String text = getText();
+		if (text != null) {
+			Font font = getFont();
+			if (font == null) {
+				font = JFaceResources.getDefaultFont();
+			}
+			dim.setSize(FigureUtilities.getTextExtents(text + "  ", font));
+		}
+		return dim;
+	}
+	
+	private Dimension calculateImageExtents() {
+		Dimension dim = new Dimension(0, 0);
+		Image image = getImage();
+		if (image != null) {
+			dim.setSize(new Dimension(image.getBounds().width + 4, image.getBounds().height));
+		}
+		return dim;
+	}
+	
+	/**
+	 * Gets the minimum size for this node.  This is the minimum size of the label (text & icon)
+	 * @return Dimension
+	 */
+	public Dimension calculateMinimumSize() {
+		return calculateMinimumLabelSize();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getUnhiglightColor()
+	 */
+	public Color getUnhiglightColor() {
+		return proxy.getUnhiglightColor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getBorderHighlightColor()
+	 */
+	public Color getBorderHighlightColor() {
+		return proxy.getBorderHighlightColor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#getBorderUnhiglightColor()
+	 */
+	public Color getBorderUnhiglightColor() {
+		return proxy.getBorderUnhiglightColor();
+	}
+
+	public boolean cacheLabel() {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	public void setCacheLabel(boolean cacheLabel) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	
+}
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/ProxyConnection.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/ProxyConnection.java
new file mode 100644
index 0000000..3821fed
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/ProxyConnection.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel;
+
+
+
+/**
+ * A model class that references a connection in the model in order to conseptually
+ * duplicate them, without actually duplicating them in the model. Useful for 
+ * visual elements. Uses visual information from the proxy.
+ * 
+ * Unlike proxy nodes, this connection does not forward to the proxy. It simply
+ * initializes its state based on the proxy node.
+ * @author Del Myers
+ *
+ */
+
+//@tag zest(bug(153466-NoNestedClientSupply(fix))) : will be used to create multiple visual connections.
+//@tag zest(bug(154259-Abstraction(fix)))
+public class ProxyConnection extends GraphModelConnection {
+	private IGraphModelConnection proxy;
+
+	/**
+	 * Creates a new proxy connection with its visuals based on the given connection.
+	 */
+	protected ProxyConnection(IGraphModelNode source, IGraphModelNode dest, IGraphModelConnection proxy) {
+		super(proxy.getGraphModel(), proxy.getExternalConnection(), source, dest);
+		this.proxy = proxy;
+		init();
+	}
+
+	private final void init() {
+		setConnectionStyle(proxy.getConnectionStyle());
+		setCurveDepth(proxy.getCurveDepth());
+		setEndAngle(proxy.getEndAngle());
+		setEndLength(proxy.getEndLength());
+		setFont(proxy.getFont());
+		setHighlightColor(proxy.getHighlightColor());
+		setImage(proxy.getImage());
+		setLineColor(proxy.getLineColor());
+		setLineStyle(proxy.getLineStyle());
+		setLineWidth(proxy.getLineWidth());
+		setStartAngle(proxy.getStartAngle());
+		setStartLength(proxy.getStartLength());
+		setText(proxy.getText());
+	}
+	
+	public IGraphModelConnection getProxy() {
+		return proxy;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/INestedGraphModelFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/INestedGraphModelFactory.java
new file mode 100644
index 0000000..882b1ba
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/INestedGraphModelFactory.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel.nested;
+
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+
+/**
+ * @author Ian Bull
+ * @deprecated
+ */
+public interface INestedGraphModelFactory {
+
+	/**
+	 * Creates a new graph model
+	 * @return
+	 */
+	public abstract NestedGraphModel createModel();
+
+	/**
+	 * Creates the model using the content provider. Uses the default given node style and connection style.
+	 * @param inputElement
+	 * @param nodeStyle
+	 * @param connectionStyle
+	 * @return
+	 */
+	//@tag zest(bug(153348-NestedStyle(fix))) : add node style and connection style
+	//	@tag zest(bug(154412-ClearStatic(fix))) : made more generic so that AbstractStylingModelFactory can do some processing in this method.
+	public abstract GraphModel createModelFromContentProvider(Object inputElement, int nodeStyle, int connectionStyle);
+
+	/**
+	 * Creates a new relationship using the content provider to get the source and destination.
+	 * @param model	The graph model.
+	 * @param data	The data object for the new connection.
+	 * @param contentProvider	The content provider which will get the source and destination nodes.
+	 * @return NestedGraphModelConnection
+	 */
+	public abstract NestedGraphModelConnection createRelationship(NestedGraphModel model,
+			Object data);
+
+	/**
+	 * Creates a new relationship and adds it to the model
+	 * @param model
+	 * @param source
+	 * @param dest
+	 * @return NestedGraphModelConnection
+	 */
+	public abstract NestedGraphModelConnection createRelationship(NestedGraphModel model,
+			Object data, Object source, Object dest);
+
+	/**
+	 * Creates a new node and adds it to the model.  If the node already exists it is just returned.
+	 * @param model	The graph model
+	 * @param data	The new node's data object
+	 * @return NestedGraphModelNode	the new or existing node
+	 */
+	public abstract NestedGraphModelNode createNode(NestedGraphModel model, Object data);
+
+}
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModel.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModel.java
new file mode 100644
index 0000000..7bd72b7
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModel.java
@@ -0,0 +1,330 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel.nested;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.swt.widgets.Canvas;
+
+
+
+/**
+ * Extends {@link GraphModel} to provider support for nested graphs.
+ * Instead of holding a list of all the nodes, the model now only
+ * holds the root node, the current node and the previous node.  All other
+ * nodes can be retrieved by traversing the children/parent hierarchy.
+ * 
+ * @author Chris Callendar
+ */
+public class NestedGraphModel extends GraphModel {
+
+	private final int STACK_SIZE = 10;
+	
+	private NestedGraphModelNode rootNode;
+	private NestedGraphModelNode currentNode;
+	private NestedGraphModelNode previousNode;
+	
+	private LinkedList backStack;
+	private LinkedList forwardStack;
+	
+	private Rectangle mainArea;
+	
+//	@tag zest(bug(152613-Client-Supplier(fix))) : allow the model to tell the view if clients/suppliers should be closed.
+	private boolean clientClosed;
+	private boolean supplierClosed;
+	
+
+	/**
+	 * Initializes the model with the given canvas.
+	 * @param canvas
+	 */
+	public NestedGraphModel(Canvas canvas) {
+		super(canvas);
+		this.backStack = new LinkedList();
+		this.forwardStack = new LinkedList();
+		this.mainArea = new Rectangle();	
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.widgets.Widget#toString()
+	 */
+	public String toString() {
+		return "NestedGraphModel {" + 
+			(rootNode != null ? "Root: " + rootNode.getText() + ", ": "") +
+			(currentNode != null ? "Current: " + currentNode.getText() + ", " : "") + 
+			connections.size() + " connections}";
+	}
+	
+	/**
+	 * @return the clientClosed
+	 */
+	public boolean isClientClosed() {
+		return clientClosed;
+	}
+	
+	/**
+	 * @param clientClosed the clientClosed to set
+	 */
+	public void setClientClosed(boolean clientClosed) {
+		this.clientClosed = clientClosed;
+	}
+	
+	/**
+	 * @return the supplierClosed
+	 */
+	public boolean isSupplierClosed() {
+		return supplierClosed;
+	}
+	
+	/**
+	 * @param supplierClosed the supplierClosed to set
+	 */
+	public void setSupplierClosed(boolean supplierClosed) {
+		this.supplierClosed = supplierClosed;
+	}
+	
+	/* (non-Javadoc)
+	 * @see ca.uvic.cs.zest.internal.graphmodel.GraphModel#removeNodeFromList(ca.uvic.cs.zest.internal.graphmodel.GraphModelNode)
+	 */
+	protected boolean removeNodeFromList(IGraphModelNode node) {
+		return true;
+	}
+	
+	
+	/**
+	 * Returns the children nodes under the current node.
+	 * @return List of NestedGraphModelNode objects which are the children of the current node
+	 */
+	public List getNodes() {
+		if ( currentNode != null ) {
+			ArrayList al = new ArrayList(  );
+			al.add( currentNode );
+			return al;
+		}
+		else { 
+			ArrayList al = new ArrayList();
+			al.add( rootNode );
+			return al;
+		}
+		
+	}
+	
+	/**
+	 * Gets the root node for this model.  If this model is of a flat graph
+	 * then the root node will be null.  Otherwise the root node will be returned.
+	 * @return NestedGraphModelNode
+	 */
+	public NestedGraphModelNode getRootNode() {
+		return rootNode;
+	}	
+	
+	/**
+	 * Sets the root node for this model.
+	 * @param rootNode
+	 */
+	public void setRootNode(NestedGraphModelNode rootNode) {
+		this.rootNode = rootNode;
+		if (currentNode == null) {
+			setCurrentNode(rootNode);
+		}
+	}
+
+	/**
+	 * Returns the current node.
+	 * @return NestedGraphModelNode
+	 */
+	public NestedGraphModelNode getCurrentNode() {
+		return currentNode;		
+	}
+	
+	/**
+	 * Sets the current node.  The previous node is added to the back stack.
+	 * @param newNode the new current node (can't be null)
+	 */
+	public void setCurrentNode(NestedGraphModelNode newNode) {
+		if (newNode == null)
+			return;
+		
+		addToBackStack(currentNode);
+		setCurrent(newNode);
+	}	
+	
+	/**
+	 * Sets the current node.  The back and forward stacks are not touched.
+	 * @param node
+	 */
+	private void setCurrent(NestedGraphModelNode node) {
+		NestedGraphModelNode old = currentNode;
+		if (currentNode != null) {
+			previousNode = currentNode;
+			previousNode.setCurrent(false);
+		}
+		currentNode = node;
+		currentNode.setCurrent(true);
+		firePropertyChange(NODE_FOCUS_PROP, old, currentNode);
+		currentNode.setChildrenVisible(true);
+		
+	}
+
+	/**
+	 * Gets the previous root node for this graph model
+	 * @return NestedGraphModelNode
+	 */
+	public	NestedGraphModelNode getPreviousRootNode() {
+		return previousNode;
+	}	
+	
+	// BACK/FORWARD/UP methods
+	
+	/**
+	 * Returns true if there are entries in the Back button stack.
+	 * @return boolean
+	 */
+	public boolean hasBackNode() {
+		return (backStack.size() > 0);
+	}
+	
+	/**
+	 * Returns true if there are entries in the Forward button stack.
+	 * @return boolean
+	 */
+	public boolean hasForwardNode() {
+		return (forwardStack.size() > 0);
+	}
+	
+	/**
+	 * Returns true if the current node has a parent (which isn't the root).
+	 * @return boolean
+	 */
+	public boolean hasParentNode() {
+		boolean hasParent = (currentNode != null) && 
+							(currentNode != rootNode) && 
+							(currentNode.getParent() != null); 
+		return hasParent;
+	}
+	
+	/**
+	 * Goes back to the previous node.
+	 */
+	public void goBack() {
+		if (hasBackNode()) {
+			addToForwardStack(currentNode);
+			NestedGraphModelNode node = popBackStack();
+			setCurrent(node);
+		}
+	}
+	
+	public void goForward() {
+		if (hasForwardNode()) {
+			addToBackStack(currentNode);
+			NestedGraphModelNode node = popForwardStack();
+			setCurrent(node);
+		}
+	}
+
+	/**
+	 * Sets the parent of the current node to the be the 
+	 * new current node.
+	 */
+	public void goUp() {
+		if (hasParentNode()) {
+			addToBackStack(currentNode);
+			setCurrent(currentNode.getCastedParent());
+		}
+	}
+	
+	/**
+	 * Adds the given node to the front of the list (top of the stack).
+	 * @param node
+	 */
+	private void addToBackStack(NestedGraphModelNode node) {
+		if (node == null)
+			return;
+
+		//  check to make sure that the top isn't the same as the new one
+		if (backStack.size() > 0) {
+			NestedGraphModelNode top = (NestedGraphModelNode)backStack.getFirst();
+			if (top == node)
+				return;
+		}
+		// if the stack is too big, remove the last node
+		if (backStack.size() >= STACK_SIZE) {
+			backStack.removeLast();
+		}
+		backStack.addFirst(node);
+	}
+	
+	/**
+	 * Adds the given node to the front of the forward stack.
+	 * @param node
+	 */
+	private void addToForwardStack(NestedGraphModelNode node) {
+		if (node == null)
+			return;
+		
+		//  check to make sure that the top isn't the same as the new one
+		if (forwardStack.size() > 0) {
+			NestedGraphModelNode top = (NestedGraphModelNode)forwardStack.getFirst();
+			if (top == node)
+				return;
+		}
+		// if the stack is too big, remove the bottom (last) node
+		if (forwardStack.size() >= STACK_SIZE) {
+			forwardStack.removeLast();
+		}
+		forwardStack.addFirst(node);
+	}
+	
+	/**
+	 * Removes the top node from the back stack.
+	 * @return NestedGraphModelNode
+	 */
+	private NestedGraphModelNode popBackStack() {
+		if (backStack.size() > 0) {
+			return (NestedGraphModelNode)backStack.removeFirst();
+		}
+		return null;
+	}
+	
+	/**
+	 * Removes the top node from the forward stack.
+	 * @return NestedGraphModelNode
+	 */
+	private NestedGraphModelNode popForwardStack() {
+		if (forwardStack.size() > 0) {
+			return (NestedGraphModelNode)forwardStack.removeFirst();
+		}
+		return null;
+	}
+
+	/**
+	 * Sets the main (scrollable) area.
+	 * @param mainArea
+	 */
+	public void setMainArea(Rectangle area) {
+		this.mainArea.setBounds(area); 
+	}
+	
+	/**
+	 * Returns a copy of the main (scrollable) area.
+	 * @return Rectangle
+	 */
+	public Rectangle getMainArea() {
+		return mainArea.getCopy();
+	}
+	
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModelConnection.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModelConnection.java
new file mode 100644
index 0000000..014f29d
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModelConnection.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel.nested;
+
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModelConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+
+
+/**
+ * Extends GraphModelConnection.  The only real purpose is to change the colors
+ * and the line widths.
+ * @deprecated by Del Myers. This connection is no longer needed. Use regular GraphModelConnections.
+ * @author Chris Callendar
+ */
+public class NestedGraphModelConnection extends GraphModelConnection {
+
+	/**
+	 * @param graphModel
+	 * @param data
+	 * @param source
+	 * @param destination
+	 */
+	public NestedGraphModelConnection(GraphModel graphModel, Object data, IGraphModelNode source,
+			IGraphModelNode destination) {
+		super(graphModel, data, source, destination);
+	}
+
+	/**
+	 * @param graphModel
+	 * @param data
+	 * @param source
+	 * @param destination
+	 * @param bidirection
+	 * @param weight
+	 */
+	public NestedGraphModelConnection(GraphModel graphModel, Object data, IGraphModelNode source,
+			IGraphModelNode destination, boolean bidirection, double weight) {
+		super(graphModel, data, source, destination, bidirection, weight);
+		// TODO Auto-generated constructor stub
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.GraphModelConnection#getColorFromWeight()
+	 *
+	protected Color getColorFromWeight() {
+		return ColorConstants.darkBlue;
+	}*/
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.GraphModelConnection#getLineWidthFromWeight()
+	 *
+	protected int getLineWidthFromWeight() {
+		return 1;
+	}*/
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModelEntityFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModelEntityFactory.java
new file mode 100644
index 0000000..a1574d1
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModelEntityFactory.java
@@ -0,0 +1,292 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel.nested;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.mylar.zest.core.internal.graphmodel.AbstractStylingModelFactory;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.messages.ZestUIMessages;
+import org.eclipse.mylar.zest.core.viewers.EntityConnectionData;
+import org.eclipse.mylar.zest.core.viewers.IGraphEntityContentProvider;
+import org.eclipse.mylar.zest.core.viewers.INestedGraphEntityContentProvider;
+import org.eclipse.swt.widgets.Canvas;
+
+
+/**
+ * A factory for creating nodes and relationships for nested graphs.
+ * 
+ * @author Chris Callendar
+ */
+//@tag bug(151327-Styles(todo)) : Use GraphItemStyler to style the graphs that are created.
+//@tag bug.160367-Refreshing.fix : Updated to use the new AbstractStylingModelFactory
+public class NestedGraphModelEntityFactory extends AbstractStylingModelFactory {
+
+		
+	public NestedGraphModelEntityFactory(StructuredViewer viewer) {
+		super(viewer);
+	}
+	
+	
+	private INestedGraphEntityContentProvider getCastedContent() {
+		return (INestedGraphEntityContentProvider)getContentProvider();
+	}
+		
+	//@tag bug(153348-NestedStyle(fix)) : add nodestyle and connectionstyle so that the model can be updated.
+//	@tag bug(154412-ClearStatic(fix)) : renamed to allow the parent to do some processing before the model is created.
+	public GraphModel createGraphModel() {
+		NestedGraphModel model = new NestedGraphModel((Canvas)getViewer().getControl());
+		doBuildGraph(model);
+		return model;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.AbstractStylingModelFactory#doBuildGraph(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel)
+	 */
+	protected void doBuildGraph(GraphModel graph) {
+		NestedGraphModel model = (NestedGraphModel) graph;
+		clearGraph(model);
+		model.setConnectionStyle(getConnectionStyle());
+		model.setNodeStyle(getNodeStyle());
+		
+		// add the root element
+		// TODO this maybe should be optional...
+		NestedGraphModelNode rootNode = new NestedGraphModelNode(model, null);
+		rootNode.setData(rootNode);
+		rootNode.setHighlightAdjacentNodes(true);
+		rootNode.setText(ZestUIMessages.VIEW_NESTED_TOP_NODE);
+		model.addNode(rootNode.getData(), rootNode);
+		
+		rootNode.setSizeInLayout(-1, -1);
+		
+		model.setRootNode(rootNode);
+		
+		Object entities[] = getContentProvider().getElements(getViewer().getInput());
+		entities = filter(getViewer().getInput(), entities);
+		// add all root the entities and recursively add their children
+		if (entities != null) {
+			for ( int i = 0; i < entities.length; i++ ) {
+				Object data = entities[i];
+				NestedGraphModelNode node = (NestedGraphModelNode) createNode(model,data);
+				node.setParent(rootNode);
+				rootNode.addChild(node);
+				node.setSizeInLayout(100, 100);
+				addChildNodes(model, data);
+			}
+			NestedGraphModelNode node = model.getRootNode();
+			//relationships have to be created only after all nodes have been
+			//otherwise, we can't connect nested nodes.
+			recursiveCreateRelationships(node);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.AbstractStylingModelFactory#createNode(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel, java.lang.Object)
+	 */
+	public IGraphModelNode createNode(GraphModel graph, Object element) {
+		NestedGraphModelNode node = getNode((NestedGraphModel)graph, element);
+		if (node == null) {
+			node = new NestedGraphModelNode((NestedGraphModel)graph,element);
+			// add the parent
+			Object parent = getCastedContent().getParent(element);
+			if (parent != null) {
+				NestedGraphModelNode parentNode = getNode((NestedGraphModel)graph, parent);
+				if (parentNode != null) {
+					node.setParent(parentNode);
+					parentNode.addChild(node);
+				}
+			}
+			// add it to the model (must be done after adding the parent!)
+			graph.addNode(element, node);
+		}
+		styleItem(node);
+		return node;
+	}
+	
+	/**
+	 * @param node
+	 */
+	private void recursiveCreateRelationships(NestedGraphModelNode node) {
+		//add the sibling, children and parent relationships
+		Object data = node.getData();
+		NestedGraphModel model = node.getNestedGraphModel();
+		Object[] related = getCastedContent().getConnectedTo(data);
+		if ( related != null ) {
+			for ( int i = 0; i < related.length; i++ ) {
+				createConnection(model, new EntityConnectionData(data, related[i]), data, related[i]);
+			}
+		}
+		for (Iterator it = node.getChildren().iterator(); it.hasNext();) {
+			recursiveCreateRelationships((NestedGraphModelNode) it.next());
+		}
+	}
+
+	/**
+	 * Recusively adds the children nodes for the given data object.  The children
+	 * are gotten from the content provider.
+	 * @param model
+	 * @param data
+	 */
+	private void addChildNodes(NestedGraphModel model, Object data) {
+		Object[] childrenData = getCastedContent().getChildren(data);
+		childrenData = filter(data, childrenData);
+		if (childrenData != null) {
+			for (int j = 0; j < childrenData.length; j++) {
+				Object childData = childrenData[j];
+				NestedGraphModelNode node = (NestedGraphModelNode) createNode(model, childData);
+				node.setSizeInLayout(100, 100);
+//				@tag bug(153348-NestedStyle(fix))
+				addChildNodes(model, childData);
+			}
+		}
+	}
+
+
+	
+	private NestedGraphModelNode getNode(NestedGraphModel model, Object data) {
+		NestedGraphModelNode node = (NestedGraphModelNode)model.getInternalNode(data);
+		return node;
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory#refresh(org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel, java.lang.Object, boolean)
+	 */
+	public void refresh(GraphModel graph, Object element, boolean updateLabels) {
+		NestedGraphModel model = (NestedGraphModel) graph;
+		NestedGraphModelNode node = (NestedGraphModelNode) model.getInternalNode(element);
+		if (node == null) {
+			IGraphModelConnection conn = model.getInternalConnection(element);
+			if (conn != null) {
+				refresh(graph, conn.getSource().getExternalNode(), updateLabels);
+				refresh(graph, conn.getDestination().getExternalNode(), updateLabels);
+			}
+			return;
+		}
+		
+		
+		Map nodesMap = graph.getNodesMap();
+//		remove all of the child nodes.
+		clearChildren(node);
+		addChildNodes(model, element);
+		reconnect(node, updateLabels);
+		//update the positions on the new nodes to match the old ones.
+		List nodes = getAllChildren(node);
+		
+		for (Iterator i = nodes.iterator(); i.hasNext();) {
+			IGraphModelNode next = (IGraphModelNode) i.next();
+			IGraphModelNode oldNode = (IGraphModelNode) nodesMap.get(next.getExternalNode());
+			if (oldNode != null) {
+				next.setPreferredLocation(oldNode.getXInLayout(), oldNode.getYInLayout());
+			}
+			reconnect(next, updateLabels);
+		}
+		
+	}
+	
+	/**
+	 * @param graph
+	 * @param element
+	 * @param refreshLabels
+	 */
+	private void reconnect(IGraphModelNode node, boolean refreshLabels) {
+		GraphModel graph = node.getGraphModel();
+		Object element = node.getExternalNode();
+		Object[] related = ((IGraphEntityContentProvider)getContentProvider()).getConnectedTo(element);
+		List connections = node.getSourceConnections();
+		LinkedList toAdd = new LinkedList();
+		LinkedList toDelete = new LinkedList();
+		LinkedList toKeep = new LinkedList();
+		HashSet oldExternalConnections = new HashSet();
+		HashSet newExternalConnections = new HashSet();
+		for (Iterator it = connections.iterator(); it.hasNext();) {
+			oldExternalConnections.add(((IGraphModelConnection)it.next()).getExternalConnection());
+		}
+		for (int i = 0; i < related.length; i++) {
+			newExternalConnections.add(new EntityConnectionData(element, related[i]));
+		}
+		for (Iterator it = oldExternalConnections.iterator(); it.hasNext();) {
+			Object next = it.next();
+			if (!newExternalConnections.contains(next)) {
+				toDelete.add(next);
+			} else {
+				toKeep.add(next);
+			}
+		}
+		for (Iterator it = newExternalConnections.iterator(); it.hasNext();) {
+			Object next = it.next();
+			if (!oldExternalConnections.contains(next)) {
+				toAdd.add(next);
+			}
+		}
+		for (Iterator it = toDelete.iterator(); it.hasNext();) {
+			graph.removeConnection(it.next());
+		}
+		toDelete.clear();
+		LinkedList newNodeList = new LinkedList();
+		for (Iterator it = toAdd.iterator(); it.hasNext();) {
+			EntityConnectionData data = (EntityConnectionData) it.next();
+			IGraphModelNode dest = graph.getInternalNode(data.dest);
+			if (dest == null) {
+				newNodeList.add(data.dest);
+			}
+			createConnection(graph, data, data.source, data.dest);
+		}
+		toAdd.clear();
+		if (refreshLabels) {
+			for (Iterator i = toKeep.iterator(); i.hasNext();) {
+				styleItem(graph.getInternalConnection(i.next()));
+			}
+		}
+		for (Iterator it = newNodeList.iterator(); it.hasNext();) {
+			//refresh the new nodes so that we get a fully-up-to-date graph.
+			refresh(graph, it.next());
+		}
+	}
+
+
+
+	/**
+	 * @param node
+	 * @return
+	 */
+	private List getAllChildren(NestedGraphModelNode node) {
+		LinkedList nodes = new LinkedList();
+		nodes.addAll(node.getChildren());
+		for (Iterator it = node.getChildren().iterator(); it.hasNext();) {
+			nodes.addAll(getAllChildren((NestedGraphModelNode) it.next()));
+		}
+		return nodes;
+	}
+
+
+	/**
+	 * @param node
+	 */
+	private void clearChildren(NestedGraphModelNode node) {
+		List children = node.getChildren();
+		for (Iterator it = children.iterator(); it.hasNext();) {
+			NestedGraphModelNode child = (NestedGraphModelNode) it.next();
+			clearChildren(child);
+		}
+		node.setParent(null);
+		node.getParent().getChildren().remove(node);
+		node.getGraphModel().removeNode(node);
+	}
+		
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModelNode.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModelNode.java
new file mode 100644
index 0000000..e9dfaf4
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModelNode.java
@@ -0,0 +1,517 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel.nested;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.layouts.NestedLayoutEntity;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Extends GraphModelNode to add methods that deal with nested graphs.
+ * 
+ * @author Chris Callendar
+ * @author Ian Bull
+ */
+public class NestedGraphModelNode extends GraphModelNode implements NestedLayoutEntity {
+
+	/*
+	 * Tree Constants
+	 */
+	public static final int SAME_NODE = 0;
+	public static final int DESCENDANT = 1;
+	public static final int ANCESTOR = 2;
+	public static final int NO_RELATION = 3;
+	public static final int PLUS_SIZE = 16;
+	private NestedGraphModelNode parent;
+	private List children;
+	private int depth; // the depth of this node. Root nodes (null parent) are
+						// at a depth 0
+	private double widthScale;
+	private double heightScale;
+	private boolean isCurrent;
+	private boolean childrenVisible;
+	private Rectangle childrenBounds;
+	private Dimension minimizedSize;
+	private Dimension fullSize;
+	
+	public NestedGraphModelNode(NestedGraphModel graphModel, Object externalNode) {
+		super(graphModel, externalNode);
+	}
+
+	public NestedGraphModelNode(NestedGraphModel graphModel, String label, Object externalNode) {
+		super(graphModel, label, externalNode);
+	}
+
+	public NestedGraphModelNode(NestedGraphModel graphModel, Image img, Object externalNode) {
+		super(graphModel, img, externalNode);
+	}
+
+	public NestedGraphModelNode(NestedGraphModel graphModel, String label, Image img, Object externalNode) {
+		super(graphModel, label, img, externalNode);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see ca.uvic.cs.zest.internal.graphmodel.GraphModelNode#initModel(java.lang.Object)
+	 */
+	protected void initModel(GraphModel graphModel, Object externalNode) {
+		super.initModel(graphModel, externalNode);
+		this.parent = null;
+		this.children = new ArrayList();
+		this.depth = 0;
+		this.widthScale = 1.0;
+		this.heightScale = 1.0;
+		this.isCurrent = false;
+		this.childrenVisible = false;
+	}
+
+	public String toString() {
+		// " {Parent: " + getParent().getText() + "}"
+		return "NestedGraphModelNode: " + getText() + ("  {" + getChildren().size() + " children}");
+	}
+
+	/**
+	 * Gets the relationship between two given nodes 
+	 *  SAME_NODE - Same
+	 *  DESCENDANT - node is a child of this
+	 *  ANCESTOR - node is a parent of this
+	 *  NO_RELATION - node is not directly related
+	 * @param that	the node to compare with this
+	 * @return int
+	 * @see #SAME_NODE
+	 * @see #ANCESTOR
+	 * @see #DESCENDANT
+	 * @see #NO_RELATION
+	 */
+	public int getRelationshipBetweenNodes(NestedGraphModelNode that) {
+		if (that == this)
+			return SAME_NODE;
+		if (this.isAncestorOf(that))
+			return ANCESTOR;
+		else if (this.isDescendantOf(that))
+			return DESCENDANT;
+		else
+			return NO_RELATION;
+	}
+
+	private boolean isAncestorOf(NestedGraphModelNode that) {
+		NestedLayoutEntity parent = that.getParent();
+		while (parent != null && parent != this) {
+			parent = parent.getParent();
+		}
+		if (parent == this)
+			return true;
+		else
+			return false;
+	}
+
+	private boolean isDescendantOf(NestedGraphModelNode that) {
+		return that.isAncestorOf(this);
+	}
+
+	/**
+	 * Returns the parent (or null if it is a root node).
+	 * 
+	 * @return NestedGraphModelNode
+	 */
+	public NestedLayoutEntity getParent() {
+		return parent;
+	}
+
+	/**
+	 * Gets the parent casted to a NestedGraphModelNode.
+	 * 
+	 * @return NestedGraphModelNode
+	 */
+	public NestedGraphModelNode getCastedParent() {
+		if (parent instanceof NestedGraphModelNode) {
+			return (NestedGraphModelNode) parent;
+		}
+		return null;
+	}
+
+	/**
+	 * Sets the parent for this node. This also sets the depth of nesting of the
+	 * node by traversing up the parent hierarchy counting the levels.
+	 * 
+	 * @param parent
+	 *            the parent to set
+	 */
+	public void setParent(NestedGraphModelNode parent) {
+		this.parent = parent;
+		this.depth = 0;
+		for (NestedLayoutEntity node = parent; node != null; node = node.getParent()) {
+			this.depth++;
+		}
+	}
+
+	public boolean isCurrent() {
+		return isCurrent;
+	}
+
+	public void setCurrent(boolean isCurrent) {
+		this.isCurrent = isCurrent;
+	}
+
+	/**
+	 * Returns the nested height of this node. Root nodes whose parent is null
+	 * will be at a depth of 0.
+	 * 
+	 * @return int the nested height
+	 */
+	public int getNestedDepth() {
+		return depth;
+	}
+
+	/**
+	 * Returns the list of the NestedGraphModelNode children nodes.
+	 * 
+	 * @return List of NestedGraphModelNode objects
+	 */
+	public List getChildren() {
+		return children;
+	}
+
+	public boolean hasChildren() {
+		return (children.size() > 0);
+	}
+
+	/**
+	 * Adds the child node if it isn't in the parent hierarchy of this node and
+	 * if it doesn't already exist in the list.
+	 * 
+	 * @param child
+	 */
+	public void addChild(NestedGraphModelNode child) {
+		if (child != null) {
+			boolean add = true;
+			for (NestedLayoutEntity node = this; node != null; node = node.getParent()) {
+				if (node.equals(child)) {
+					add = false;
+					break;
+				}
+			}
+			if (add && !children.contains(child)) {
+				children.add(child);
+			}
+			childrenBounds = null; // reset the size - will be calculated again
+		}
+	}
+
+	/**
+	 * Removes the given node from the list of children.
+	 * 
+	 * @param nodeToRemove
+	 * @return boolean if it was removed
+	 */
+	public boolean removeChild(IGraphModelNode nodeToRemove) {
+		boolean removed = false;
+		if (nodeToRemove != null) {
+			removed = children.remove(nodeToRemove);
+		}
+		if (removed) {
+			childrenBounds = null; // reset the size - will be calculated again
+		}
+		return removed;
+	}
+
+	/**
+	 * Returns true if the children are visible.
+	 * 
+	 * @return boolean
+	 */
+	public boolean getChildrenVisible() {
+		return childrenVisible;
+	}
+
+	/**
+	 * Sets if the children are visible and adjusts the size appropriately.
+	 * 
+	 * @param visible
+	 */
+	public void setChildrenVisible(boolean visible) {
+		if (visible) {
+			showChildren();
+		} else {
+			hideChildren();
+		}
+	}
+
+	/**
+	 * Hides the children and collapses the node to just the label.
+	 */
+	public void hideChildren() {
+		childrenVisible = false;
+		Dimension size = getFullSize();
+		super.setSizeInLayout(size.width, size.height);
+		this.firePropertyChange(FORCE_REDRAW, null, null);
+	}
+
+	/**
+	 * Displays the children and expands the node.
+	 */
+	public void showChildren() {
+		childrenVisible = true;
+		Dimension size = getFullSize();
+		super.setSizeInLayout(size.width, size.height);
+		this.firePropertyChange(FORCE_REDRAW, null, null);
+	}
+
+	/**
+	 * Gets the full size of the node without scaling and with children shown.
+	 * 
+	 * @return Dimension
+	 */
+	public Dimension getFullSize() {
+		if (fullSize == null) {
+			fullSize = calculateMinimumSize();
+		}
+		return fullSize.getCopy();
+	}
+
+	/**
+	 * Gets the size of just the plus/minus and icon and text.
+	 * 
+	 * @return Dimension
+	 */
+	public Dimension getMinimizedSize() {
+		if (minimizedSize == null) {
+			minimizedSize = calculateMinimumLabelSize();
+			minimizedSize.width = Math.max(minimizedSize.width, getFullSize().width);
+		}
+		return minimizedSize.getCopy();
+	}
+
+	/**
+	 * Sets the size of the node. Do not use this method if you want to minize
+	 * the node (label only). Call hideChildren() instead. You can also call
+	 * showChildren() to show the full size.
+	 * 
+	 * @see org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode#setSizeInLayout(double,
+	 *      double)
+	 */
+	public void setSizeInLayout(double width, double height) {
+		fullSize = new Dimension((int) width, (int) height);
+		super.setSizeInLayout(width, height);
+	}
+
+	/**
+	 * Currently this always returns 1
+	 * 
+	 * @return
+	 */
+	// public double getScale() {
+	// return (isCurrent() ? 1 : scale);
+	// }
+
+	public double getWidthScale() {
+		return widthScale;
+	}
+
+	public double getHeightScale() {
+		return heightScale;
+	}
+
+	public void setScale(double w, double h) {
+		this.widthScale = w;
+		this.heightScale = h;
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see ca.uvic.cs.zest.internal.graphmodel.GraphModelNode#calculateMinimumLabelSize()
+	 */
+	public Dimension calculateMinimumLabelSize() {
+		if (labelSize == null) {
+			labelSize = super.calculateMinimumLabelSize();
+			if (hasChildren()) {
+				labelSize.expand(PLUS_SIZE + 4, Math.max(PLUS_SIZE - labelSize.height, 0));
+			}
+		}
+		return labelSize;
+	}
+
+	/**
+	 * Calculates the minimum size of this node without taking scaling into
+	 * account. This is the full size of the label and the children.
+	 * 
+	 * @see ca.uvic.cs.zest.internal.graphmodel.IGraphModelNode#calculateMinimumSize()
+	 */
+	public Dimension calculateMinimumSize() {
+		Dimension labelSize = calculateMinimumLabelSize();
+		Rectangle childSize = calculateMinimumChildrenBounds();
+		int width = childSize.width;
+		int height = childSize.height;
+		width = Math.max(width, labelSize.width);
+		height += labelSize.height;
+		return new Dimension(width, height);
+	}
+
+	/**
+	 * Gets the minimum size for the children.
+	 * 
+	 * @return Dimension
+	 */
+	public Rectangle calculateMinimumChildrenBounds() {
+		if (childrenBounds == null) {
+			childrenBounds = new Rectangle();
+			for (Iterator iter = getChildren().iterator(); iter.hasNext();) {
+				IGraphModelNode node = (IGraphModelNode) iter.next();
+				double x = node.getXInLayout();
+				double y = node.getYInLayout();
+				if (node instanceof GraphModelNode) {
+					((GraphModelNode)node).calculateMinimumLabelSize();
+				}
+				double width = x + Math.max(node.getWidthInLayout(), labelSize.width);
+				double height = y + Math.max(node.getHeightInLayout(), labelSize.height);
+				childrenBounds.x = (int) Math.min(childrenBounds.x, x);
+				childrenBounds.y = (int) Math.min(childrenBounds.y, y);
+				childrenBounds.width = (int) Math.max(childrenBounds.width, width);
+				childrenBounds.height = (int) Math.max(childrenBounds.height, height);
+			}
+		}
+		return childrenBounds;
+	}
+
+	public NestedGraphModel getNestedGraphModel() {
+		return (NestedGraphModel) this.getGraphModel();
+	}
+	
+	/**
+	 * Finds all the nodes that are connected to this node or its children.
+	 * @return a list containing NestedGraphModelNodes.
+	 */
+//	@tag zest(bug(150585-TopArcs(fix)))
+	public List getNodesConnectedTo() {
+		List connections = getConnectionsTo();
+		//@tag zest(bug(unreported(fix))) : there should be only one copy of each node.
+		HashSet targets = new HashSet();
+		for (Iterator i = connections.iterator(); i.hasNext();) {
+			targets.add(((IGraphModelConnection)i.next()).getDestination());
+		}
+		return Arrays.asList(targets.toArray());
+	}
+	
+	public List getConnectionsTo() {
+		return recursiveGetConnectionsTo(this, this);
+	}
+	/**
+	 * Recursively finds the nodes that are connected to the currentNode and its children.
+	 * @param currentNode the current node to check.
+	 * @param topNode the top node that all nodes are guaranteed to be children of.
+	 * @return the list of nodes.
+	 */
+	private List recursiveGetConnectionsTo(NestedGraphModelNode currentNode, NestedGraphModelNode topNode) {
+		List connectedTo = new ArrayList();
+		List sourceConnections = currentNode.getSourceConnections();
+		for (Iterator i = sourceConnections.iterator(); i.hasNext();) {
+			IGraphModelConnection c = (IGraphModelConnection) i.next();
+			//@tag zest(bug(unreported(fix))) : it is possible for a nested node to be connected to a non nested node.
+			if (!(c.getDestination() instanceof NestedGraphModelNode)) continue;
+			NestedGraphModelNode target = (NestedGraphModelNode) c.getDestination();
+			if (topNode.getRelationshipBetweenNodes(target) != NestedGraphModelNode.ANCESTOR)
+				connectedTo.add(c);
+		}
+		for (Iterator i = currentNode.getChildren().iterator(); i.hasNext();) {
+			connectedTo.addAll(recursiveGetConnectionsTo((NestedGraphModelNode) i.next(), topNode));
+		}
+		return connectedTo;
+	}
+	
+	
+	/**
+	 * Finds all the nodes that are connected from this node or its children.
+	 * @return a list containing NestedGraphModelNodes.
+	 */
+	//@tag zest(bug(150585-TopArcs(fix)))
+	public List getNodesConnectedFrom() {
+		List connections = getConnectionsFrom();
+		//@tag zest(bug(unreported(fix))) : there should only be one copy of each node in the list.
+		HashSet sources = new HashSet();
+		for (Iterator i = connections.iterator(); i.hasNext();) {
+			sources.add(((IGraphModelConnection)i.next()).getSource());
+		}
+		return Arrays.asList(sources.toArray());
+	}
+	
+	public List getConnectionsFrom() {
+		return recursiveGetConnectionsFrom(this, this);
+	}
+	
+	
+	/**
+	 * Recursively finds all nodes that are connected "from" the currentNode and its children.
+	 * @param currentNode the current node to check.
+	 * @param topNode the top node that all nodes are guaranteed to be children of.
+	 * @return the list of nodes.
+	 */
+	private List recursiveGetConnectionsFrom(NestedGraphModelNode currentNode, NestedGraphModelNode topNode) {
+		List connectedFrom = new ArrayList();
+		List targetConnections = currentNode.getTargetConnections();
+		for (Iterator i = targetConnections.iterator(); i.hasNext();) {
+			IGraphModelConnection c = (IGraphModelConnection) i.next();
+			//@tag zest(bug(unreported(fix))) : it is possible for nested nodes to be connected to non nested nodes.
+			if (!(c.getSource() instanceof NestedGraphModelNode)) continue;
+			NestedGraphModelNode source = (NestedGraphModelNode) c.getSource();
+			if (topNode.getRelationshipBetweenNodes(source) != NestedGraphModelNode.ANCESTOR)
+				connectedFrom.add(c);
+		}
+		for (Iterator i = currentNode.getChildren().iterator(); i.hasNext();) {
+			connectedFrom.addAll(recursiveGetConnectionsFrom((NestedGraphModelNode) i.next(), topNode));
+		}
+		return connectedFrom;
+	}
+	
+	/**
+	 * Finds the highest common parent between this node and that node.
+	 * @param that the node to check against.
+	 * @return the highest common parent between the nodes, or null if none.
+	 */
+	public NestedGraphModelNode findCommonParent(NestedGraphModelNode that) {
+		if (this == that) return this.getCastedParent();
+		
+		LinkedList thisParentQueue = new LinkedList();
+		LinkedList thatParentQueue = new LinkedList();
+		NestedGraphModelNode node = this;
+		while (node != null) {
+			thisParentQueue.addFirst(node);
+			node = node.getCastedParent();
+		}
+		node = that;
+		while (node != null) {
+			thatParentQueue.addFirst(node);
+			node = node.getCastedParent();
+		}
+		int limit = Math.min(thisParentQueue.size(), thatParentQueue.size());
+		int i;
+		for (i = 0; i < limit; i++) {
+			if (thisParentQueue.get(i) != thatParentQueue.get(i)) break;
+		}
+		if (i >= limit) return null; //shouldn't happen.
+		return (NestedGraphModelNode) thisParentQueue.get(i-1);
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModelRootNode.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModelRootNode.java
new file mode 100644
index 0000000..ad5a648
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedGraphModelRootNode.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel.nested;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * The root model node.
+ * 
+ * @author Chris Callendar
+ */
+public class NestedGraphModelRootNode extends NestedGraphModelNode {
+
+	private static final Image IMG_HOME = ImageDescriptor.createFromFile(NestedGraphModelRootNode.class, "/icons/home.gif").createImage();
+
+	/**
+	 * Creates a new root node with the text "Root" and the home icon.
+	 * The data is set to be null.
+	 * @param model the model
+	 */
+	public NestedGraphModelRootNode(NestedGraphModel model) {
+		super(model, "Root", IMG_HOME, null);
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedPane.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedPane.java
new file mode 100644
index 0000000..f86fa10
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NestedPane.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel.nested;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.NonNestedProxyNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.ProxyConnection;
+
+
+/**
+ * @author Ian bull
+ */
+//@tag bug(152613-Client-Supplier(fix))
+public class NestedPane {
+
+	public static final int SUPPLIER_PANE = 0;
+	public static final int MAIN_PANE = 1;
+	public static final int CLIENT_PANE = 2;
+	private boolean closedState = false;
+	
+	private	NestedGraphModel nestedGraphModel = null;
+	private int paneType = 0;
+	//@tag bug(153466-NoNestedClientSupply(fix)) : must cache the children in order to avoid making extra proxies.
+	private List children = null;
+	public NestedPane( int paneType ) {
+		this.paneType = paneType;
+		children = new ArrayList();
+		
+	}
+	
+	public void setModel( NestedGraphModel model ) {
+//		@tag bug(152613-Client-Supplier(fix)) : set the initial closed state based on the model.
+		this.nestedGraphModel = model;
+		if (model == null) return;
+		switch(paneType) {
+		case CLIENT_PANE:
+			closedState = model.isClientClosed();
+			this.children = createProxies(nestedGraphModel.getCurrentNode().getConnectionsTo(), true);
+			break;
+		case SUPPLIER_PANE:
+			closedState = model.isSupplierClosed();
+			this.children = createProxies(nestedGraphModel.getCurrentNode().getConnectionsFrom(), false);
+			break;
+		case MAIN_PANE:
+			this.children = Arrays.asList(new Object[] {nestedGraphModel.getCurrentNode()});
+			break;
+		default:
+			this.children = Collections.EMPTY_LIST;
+			closedState = false;
+		}
+	}
+	
+	public NestedGraphModel getModel() {
+		return this.nestedGraphModel;
+	}
+	
+	public int getPaneType() {
+		return this.paneType;
+	}
+	
+	/**
+	 * Refreshes the children from the proxies listed in the model.
+	 *
+	 */
+	public void refreshChildren() {
+		List proxies = nestedGraphModel.getProxyConnections();
+		NestedGraphModelNode topNode = nestedGraphModel.getCurrentNode();
+		List connections;
+		boolean to = false;
+		switch (getPaneType()) {
+		case CLIENT_PANE : 
+			connections = topNode.getConnectionsTo();
+			to = true;
+			break;
+		case SUPPLIER_PANE:
+			connections = topNode.getConnectionsFrom();
+			break;
+		case MAIN_PANE:
+			this.children = Arrays.asList(new Object[] {nestedGraphModel.getCurrentNode()});
+		default: return;
+		}
+		this.children = new ArrayList();
+		Iterator i = proxies.iterator();
+		while (i.hasNext()) {
+			ProxyConnection conn = (ProxyConnection) i.next();
+			IGraphModelConnection referenced = conn.getProxy();
+			Object end = (to) ? conn.getDestination() : conn.getSource();
+			if (end instanceof NonNestedProxyNode) {
+				if (connections.contains(referenced) && ! this.children.contains(end)) {
+					this.children.add(end);
+				} 
+			}
+		}
+	}
+
+	public List getChildren() {
+		return children;
+	}
+	
+	/**
+	 * Creates proxy nodes for the given list of connections. Visible proxy connections
+	 * are also created and added to the nodes.
+	 * @param connections the list of connections.
+	 * @return The list of proxy nodes and connections
+	 */
+	private List createProxies(List connections, boolean to) {
+		LinkedList proxies = new LinkedList();
+		HashMap modelNodes = new HashMap();
+		for (Iterator i = connections.iterator(); i.hasNext();) {
+			IGraphModelConnection conn = (IGraphModelConnection) i.next();
+			NestedGraphModelNode node =	null;
+			if (to) {
+				node = (NestedGraphModelNode) conn.getDestination();
+			} else {
+				node = (NestedGraphModelNode) conn.getSource();
+			}
+			NonNestedProxyNode proxy = (NonNestedProxyNode) modelNodes.get(node);
+			if (proxy == null) {
+				proxy = node.getGraphModel().createProxyNode(node);
+				modelNodes.put(node,proxy);
+				proxies.add(proxy);
+			}
+			if (!to) {
+				node.getGraphModel().createProxyConnection(proxy, conn.getDestination(), conn);	
+			} else {
+				node.getGraphModel().createProxyConnection(conn.getSource(), proxy, conn);
+			}
+		}
+		return proxies;
+	}
+
+	/**
+     * Removes a proxy node from the list of children.
+	 */
+	public void removeProxy(NonNestedProxyNode proxy) {
+		this.children.remove(proxy);
+	}
+	
+	/**
+     * @return true iff the state of this panel is closed.
+     */
+	public boolean isClosed() {
+		return closedState;
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NodeChildrenComparator.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NodeChildrenComparator.java
new file mode 100644
index 0000000..fb0f41d
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphmodel/nested/NodeChildrenComparator.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphmodel.nested;
+
+import java.util.Comparator;
+
+
+/**
+ * Compares NestedGraphModelNode objects based on how many children a node has.
+ * Nodes with the most children will be first and nodes with no children will be last.
+ * It also sorts nodes with the same number of children alphabetically.
+ * 
+ * @author Chris Callendar
+ */
+public class NodeChildrenComparator implements Comparator {
+
+	public NodeChildrenComparator() {
+		super();
+	}
+
+	/**
+	 * Compares two NestedGraphModelNode objects based on the number of
+	 * children each one has.  The node with more children will be first.
+	 * If the nodes have the same number of children then the nodes are sorted
+	 * by name (getText()). 
+	 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+	 */
+	public int compare(Object o1, Object o2) {
+		if ((o1 instanceof NestedGraphModelNode) && (o2 instanceof NestedGraphModelNode)) {
+			return compare((NestedGraphModelNode)o1, (NestedGraphModelNode)o2);
+		}
+		return 0;
+	}
+	
+	private int compare(NestedGraphModelNode node1, NestedGraphModelNode node2) {
+		int rv = 0;
+		int c1 = node1.getChildren().size();
+		int c2 = node2.getChildren().size();
+		if (c1 != c2) {
+			rv = c2 - c1;	// put the node with more children first
+		} else {
+			String t1 = node1.getText();
+			String t2 = node2.getText();
+			if (t1 != null) {
+				rv = t1.compareTo(t2);
+			}
+		}
+		return rv;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/SpringGraphViewerImpl.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/SpringGraphViewerImpl.java
new file mode 100644
index 0000000..8d6bf8e
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/SpringGraphViewerImpl.java
@@ -0,0 +1,550 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.KeyHandler;
+import org.eclipse.gef.KeyStroke;
+import org.eclipse.gef.MouseWheelHandler;
+import org.eclipse.gef.MouseWheelZoomHandler;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+import org.eclipse.gef.editparts.LayerManager;
+import org.eclipse.gef.editparts.ZoomListener;
+import org.eclipse.gef.editparts.ZoomManager;
+import org.eclipse.gef.ui.actions.ZoomInAction;
+import org.eclipse.gef.ui.actions.ZoomOutAction;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.core.internal.gefx.GraphRootEditPart;
+import org.eclipse.mylar.zest.core.internal.gefx.IPanningListener;
+import org.eclipse.mylar.zest.core.internal.gefx.ThreadedGraphicalViewer;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphEditPartFactory;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphNodeEditPart;
+import org.eclipse.mylar.zest.core.viewers.IGraphContentProvider;
+import org.eclipse.mylar.zest.core.viewers.SpringGraphViewer;
+import org.eclipse.mylar.zest.layouts.LayoutAlgorithm;
+import org.eclipse.mylar.zest.layouts.LayoutStyles;
+import org.eclipse.mylar.zest.layouts.Stoppable;
+import org.eclipse.mylar.zest.layouts.algorithms.AbstractLayoutAlgorithm;
+import org.eclipse.mylar.zest.layouts.algorithms.FadeLayoutAlgorithm;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Widget;
+
+
+/**
+ * Simple GEF viewer used to display graphical layouts.
+ * 
+ * @author Ian Bull
+ * @author Chris Callendar
+ */
+public class SpringGraphViewerImpl extends ThreadedGraphicalViewer implements IPanningListener, ZoomListener {
+	
+	private AbstractLayoutAlgorithm layoutAlgorithm = null;
+	private Stoppable layoutThread = null;
+	private GraphModel model = null;
+	private IStylingGraphModelFactory modelFactory = null;
+	
+	/** Indicates if marquee (multiple) selection of nodes is allowed. */
+	private boolean allowMarqueeSelection;
+
+	/* irbull: These were the force directed settings
+	private boolean noOverlappingNodes = false;
+	private boolean stabilize = false;
+	private boolean enforceBounds = false;
+	private boolean directedGraph = false;
+	*/
+	private int style = ZestStyles.NONE;
+	
+	/** 
+	 * Indicates if panning (moving the canvas essentially) is allowed.  This
+	 * can only be allowed if marquee selection is not allowed.
+	 */ 
+	private boolean allowPanning;
+	
+	/** If the layout algorithm was running before panning started. */
+	private boolean wasRunningBeforePanning = false;
+	
+	
+	/**
+	 * SpringGraphViewerImpl constructor.
+	 * @param composite	the composite object
+	 * @param style	The style for this viewer. 
+	 * 				Note marquee selection can only be enabled if panning is not enabled.
+	 * @see ZestStyles#PANNING
+	 * @see ZestStyles#MARQUEE_SELECTION
+	 * @see ZestStyles#NO_OVERLAPPING_NODES
+	 * @see ZestStyles#STABILIZE
+	 * @see ZestStyles#ENFORCE_BOUNDS
+	 * @see ZestStyles#DIRECTED_GRAPH
+	 */
+	public SpringGraphViewerImpl(Composite composite, int style) {
+		super(composite);
+		this.setStyle( style );
+		this.addSelectionChangedListener( new _selectionChangedListener() );
+	}	
+	
+	/**
+	 * Sets the style on the SpringGraphViewer
+	 * @param style	The style for this viewer. 
+	 * 				Note marquee selection can only be enabled if panning is not enabled.
+	 * @see ZestStyles#PANNING
+	 * @see ZestStyles#MARQUEE_SELECTION
+	 * @see ZestStyles#NO_OVERLAPPING_NODES
+	 * @see ZestStyles#STABILIZE
+	 * @see ZestStyles#ENFORCE_BOUNDS
+	 * @see ZestStyles#DIRECTED_GRAPH
+	 */
+	public void setStyle( int style ) {
+		this.style = style;
+		/* irbull: These were the Force Directed Settings
+		this.noOverlappingNodes = ZestStyles.checkStyle(style, ZestStyles.NO_OVERLAPPING_NODES);
+		this.stabilize = ZestStyles.checkStyle(style, ZestStyles.STABILIZE);
+		this.enforceBounds = ZestStyles.checkStyle(style, ZestStyles.ENFORCE_BOUNDS);
+		*/
+		this.allowPanning = ZestStyles.checkStyle(style, ZestStyles.PANNING);
+		this.allowMarqueeSelection = !allowPanning && ZestStyles.checkStyle(style, ZestStyles.MARQUEE_SELECTION);
+	}
+	
+	
+	/**
+	 * Gets the style on the SpringGraphViewer
+	 * @return
+	 */
+	public int getStyle( ) {
+		return this.style;
+	}
+	
+	/**
+	 * Sets the model and initializes the layout algorithm.
+	 * @see org.eclipse.mylar.zest.core.internal.gefx.ThreadedGraphicalViewer#setContents(java.lang.Object)
+	 */
+	public void setContents(GraphModel model, IStylingGraphModelFactory modelFactory) {
+		super.setContents(model);
+		this.model = model;
+		this.modelFactory = modelFactory;
+		
+		Dimension d = this.getCanvasSize();
+		
+		layoutAlgorithm = new FadeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
+		//((FadeLayoutAlgorithm)layoutAlgorithm).setRandom(false);
+		//((FadeLayoutAlgorithm)layoutAlgorithm).setIterations(1000);
+		/* irbull, these were the force directed settings
+		((SpringLayoutAlgorithm) layoutAlgorithm).setSpringLengthRange(60, 225);
+		((SpringLayoutAlgorithm) layoutAlgorithm).setStabilize(stabilize);
+		((SpringLayoutAlgorithm) layoutAlgorithm).setEnforceBounds(enforceBounds);
+		((SpringLayoutAlgorithm) layoutAlgorithm).setMinimumStabilizeDistance(ForceDirectedAlgorithm.DEFAULT_MIN_STABILIZE_DISTANCE);
+		((SpringLayoutAlgorithm) layoutAlgorithm).setOverlappingNodesAllowed(!noOverlappingNodes);
+		*/
+		layoutThread = layoutAlgorithm.getLayoutThread(model.getNodesArray(), model.getConnectionsArray(),  5D, 5D, (double)d.width,(double) d.height, true);
+		
+		this.addThread(layoutThread);		
+		//this.addThread(new FreqUpdater());
+		this.addControlListener(new ControlListener() {
+			private boolean minimized = false;
+			private boolean wasRunning = false;
+			public void controlMoved(ControlEvent e) { }
+			public void controlResized(ControlEvent e) {
+				// handle minimized case
+				Dimension d = SpringGraphViewerImpl.this.getCanvasSize();
+				if (d.isEmpty()) {
+					wasRunning = layoutAlgorithm.isRunning() && !layoutAlgorithm.isPaused();
+					layoutAlgorithm.pause();
+					minimized = true;
+				} else {
+					layoutAlgorithm.setLayoutArea(5, 5, Math.max(10, d.width - 60), Math.max(10, d.height - 30));
+					if (minimized) {
+						minimized = false;
+						if (wasRunning) {
+							layoutAlgorithm.resume();
+						}
+					}
+				}
+			}
+		});		
+		
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.ui.parts.GraphicalViewerImpl#createDefaultRoot()
+	 */
+	//@tag zest.bug.156617ClearViewer.fix : create the correct default root.
+	protected void createDefaultRoot() {
+		GraphRootEditPart root = new GraphRootEditPart(this, allowMarqueeSelection, allowPanning);
+		this.setRootEditPart(root);
+	}
+	
+	private GraphRootEditPart getCastedRoot() {
+		return (GraphRootEditPart)getRootEditPart();
+	}
+	
+		
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.ui.parts.GraphicalEditor#configureGraphicalViewer()
+	 */
+	protected void configureGraphicalViewer() {
+		GraphRootEditPart root = getCastedRoot();
+		//@tag zest.bug.156617ClearViewer.fix : just clear the children.
+		getCastedRoot().clear();
+		//setProperty(MouseWheelHandler.KeyGenerator.getKey(SWT.NONE), this);
+		
+		List zoomLevels = new ArrayList(3);
+		zoomLevels.add(ZoomManager.FIT_ALL);
+		zoomLevels.add(ZoomManager.FIT_WIDTH);
+		zoomLevels.add(ZoomManager.FIT_HEIGHT);
+	
+		ZoomManager zoomMgr = root.getZoomManager();
+		zoomMgr.setZoomLevelContributions(zoomLevels);
+
+		zoomMgr.addZoomListener(this);
+		IAction zoomIn = new ZoomInAction(zoomMgr);
+		IAction zoomOut = new ZoomOutAction(zoomMgr);
+		
+		
+		KeyHandler handler = getKeyHandler();
+		if (handler == null) {
+			handler = new KeyHandler();
+			this.setKeyHandler(handler);
+		}
+		
+		// so many zoom choices, so little time!
+	
+		getKeyHandler().put(KeyStroke.getPressed('+', 43, SWT.CTRL), zoomIn);
+		getKeyHandler().put(KeyStroke.getPressed('+', SWT.KEYPAD_ADD, SWT.CTRL), zoomIn);
+		getKeyHandler().put(KeyStroke.getPressed('=', 61, SWT.CTRL), zoomIn);
+		getKeyHandler().put(KeyStroke.getPressed('-', 45, SWT.CTRL), zoomOut);
+		getKeyHandler().put(KeyStroke.getPressed('-', SWT.KEYPAD_SUBTRACT, SWT.CTRL), zoomOut);
+		this.setProperty(MouseWheelHandler.KeyGenerator.getKey(SWT.CTRL), MouseWheelZoomHandler.SINGLETON);
+		this.setEditPartFactory(new GraphEditPartFactory(root));
+	
+	}
+
+	/**
+	 * Gets an array of the selected model elements (Widget objects).
+	 * @return Widget[]
+	 */
+	public Widget[] getSelectedModelElements() {
+		Widget[] items = new Widget[ getSelectedEditParts().size() ];
+		int i = 0;
+		for ( Iterator iterator = getSelectedEditParts().iterator(); iterator.hasNext(); ) {
+			AbstractGraphicalEditPart editPart =(AbstractGraphicalEditPart) iterator.next(); 
+			Object modelElement = (Object)editPart.getModel();
+			if ( modelElement.equals(LayerManager.ID)) {
+				items[i++] = getControl();
+			} else {
+				items[i++] = (Widget)modelElement;
+			}
+		}
+		return items;
+	}
+	
+    public void setSelection(ISelection selection) {
+    	if (!(selection instanceof IStructuredSelection))
+    		return;
+    	List orderedSelection = ((IStructuredSelection)selection).toList();
+    	ArrayList editPartSelection = new ArrayList( orderedSelection.size() );
+    	for( int i = 0; i < orderedSelection.size(); i++ ) {
+    		editPartSelection.add( i, orderedSelection.get(i));
+    	}
+    	super.setSelection( new StructuredSelection( editPartSelection )  );
+    }
+    
+    /**
+     * @see SpringGraphViewerImpl#centerNode(IGraphModelNode)
+     */
+    public void setCenterSelection( IGraphModelNode nodeToCenter, int x, int y ) {
+    	//TODO: Really make this the center, note this is harder when we are in a SASHForm
+    	nodeToCenter.setLocationInLayout(x,y);
+    	StructuredSelection selection = new StructuredSelection( new Object[]{nodeToCenter} );
+    	setSelection( selection );
+    }
+	
+    /**
+     * This is an alternate way of centering the given node.  It 
+     * pans the canvas to make the given node be at the center of the viewer.
+     * @param nodeToCenter	The node to center (assumed not null).
+     */
+    public void centerNodeInCanvas(IGraphModelNode nodeToCenter) {
+    	Dimension dim = getTranslatedCanvasSize();
+    	int cx = (dim.width / 2);
+    	int cy = (dim.height / 2);
+		int dx = cx - (int)nodeToCenter.getXInLayout();
+		int dy = cy - (int)nodeToCenter.getYInLayout();
+		panningStart();
+		panning(dx, dy);
+		panningEnd();    	
+    }
+    
+    /**
+     * Indicates that panning has started.  Pauses the layout algorithm if it is running.  
+     * @see org.eclipse.mylar.zest.core.internal.graphviewer.IPanningListener#panningStart()
+     */
+    public void panningStart() {
+    	wasRunningBeforePanning = layoutAlgorithm.isRunning() && !layoutAlgorithm.isPaused();
+    	if (wasRunningBeforePanning) {
+    		layoutAlgorithm.pause();
+    	}
+    }
+    
+    /**
+     * Handles a change in position due to panning.  Tells the {@link SpringGraphViewer}
+     * to move all the nodes.
+     * @param dx	the change in x position
+     * @param dy	the change in y position
+     * @see org.eclipse.mylar.zest.core.internal.graphviewer.IPanningListener#panning(int, int)
+     */
+    public void panning(int dx, int dy) {
+    	// @tag zest(bug(153356)) : Revist panning support for static graph
+    	//layoutAlgorithm.moveAllEntities(dx, dy);
+    }
+    
+    /**
+     * Indicates that panning has ceased.  Resumes the layout algorithm if it was running
+     * before panning started.
+     * @see org.eclipse.mylar.zest.core.internal.graphviewer.IPanningListener#panningEnd()
+     */
+    public void panningEnd() {
+    	if (wasRunningBeforePanning) {
+    		layoutAlgorithm.resume();
+    	}
+    }
+
+	/**
+	 * Creates a new relationship between the source node and the destination node.
+	 * If either node doesn't exist then it will be created.
+	 * @param connection	The connection data object.
+	 * @param srcNode		The source node data object.
+	 * @param destNode		The destination node data object.
+	 */
+	public void addRelationship(Object connection, Object srcNode, Object destNode) {
+		// create the new relationship
+		IGraphModelConnection newConnection = modelFactory.createConnection(model, connection, srcNode, destNode);
+
+		// add it to the layout algorithm
+		layoutAlgorithm.addRelationship(newConnection);
+	}
+	
+	/**
+	 * Adds a new relationship given the connection.  It will use the content provider 
+	 * to determine the source and destination nodes.
+	 * @param connection	The connection data object.
+	 */
+	public void addRelationship (Object connection) {
+		if (model.getInternalConnection(connection) == null) {
+			if (modelFactory.getContentProvider() instanceof IGraphContentProvider) {
+			IGraphContentProvider content = ((IGraphContentProvider)modelFactory.getContentProvider());
+			Object source = content.getSource(connection);
+			Object dest = content.getDestination(connection);
+			// create the new relationship
+			IGraphModelConnection newConnection = modelFactory.createConnection(model, connection, source, dest);
+			// add it to the layout algorithm
+			layoutAlgorithm.addRelationship(newConnection);
+			} else {
+				throw new UnsupportedOperationException();
+			}
+		}
+	}
+	
+	/**
+	 * Updates the connection with the given weight.  
+	 * The weight should be in {-1, [0-1]}.  
+	 * A weight of -1 means that there is no force/tension between the nodes.
+	 * A weight of 0 results in the maximum spring length being used (farthest apart).
+	 * A weight of 1 results in the minimum spring length being used (closest together).
+	 * @param connection	The connection object.
+	 * @param weight		The new weight for the connection.
+	 */
+	public void updateRelationshipWeight(Object connection, double weight) {
+		IGraphModelConnection relationship = model.getInternalConnection(connection);
+		if (relationship != null) {
+			relationship.setWeightInLayout(weight);
+		}
+	}
+
+	/**
+	 * Removes the given connection object from the layout algorithm and the model.
+	 * @param connection
+	 */
+	public void removeRelationship(Object connection) {
+		IGraphModelConnection relation = model.getInternalConnection(connection);
+		
+		if (relation != null) {
+			// remove the relationship from the layout algorithm
+			layoutAlgorithm.removeRelationship(relation);
+			
+			// remove the relationship from the model
+			model.removeConnection(relation);
+		}
+	}
+
+	
+	/**
+	 * Creates a new node and adds it to the graph.  If it already exists nothing happens.
+	 * @param newNode
+	 */
+	public void addNode(Object element) {
+		if (model.getInternalNode(element) == null ) {
+			// create the new node
+			IGraphModelNode newNode = modelFactory.createNode(model, element);
+			
+			// add it to the layout algorithm
+			layoutAlgorithm.addEntity(newNode);
+		}
+	}
+
+	/**
+	 * Removes the given element from the layout algorithm and the model.
+	 * @param element	The node element to remove.
+	 */
+	public void removeNode(Object element) {
+		IGraphModelNode node = model.getInternalNode(element);
+		
+		if (node != null) {
+			// remove the node from the layout algorithm and all the connections
+			layoutAlgorithm.removeEntity(node);
+			layoutAlgorithm.removeRelationships(node.getSourceConnections());
+			layoutAlgorithm.removeRelationships(node.getTargetConnections());
+			
+			// remove the node and it's connections from the model
+			model.removeNode(node);
+		}
+	}
+
+	/**
+	 * Pauses layout algorithm if it is running not paused.
+	 */
+	public void pauseLayoutAlgorithm() {
+		if ((layoutAlgorithm != null) && layoutAlgorithm.isRunning()) {
+			if (!layoutAlgorithm.isPaused()) {
+				layoutAlgorithm.pause();
+			}
+		}
+	}
+
+	/**
+	 * Resumes the layout algorithm if it is running and paused.
+	 */
+	public void resumeLayoutAlgorithm() {
+		if ((layoutAlgorithm != null) && layoutAlgorithm.isRunning()) {
+			if (layoutAlgorithm.isPaused()) {
+				layoutAlgorithm.resume();
+			}
+		}
+	}
+	
+	/**
+	 * Stops the layout algorithm if it is running.
+	 */
+	public void stopLayoutAlgorithm() {
+		if ((layoutAlgorithm != null) && layoutAlgorithm.isRunning()) {
+			layoutAlgorithm.stop();
+		}
+	}
+	
+	/**
+	 * Restarts the layout algorithm.  This will do nothing 
+	 * if the algorithm is already running.
+	 */
+	public void restartLayoutAlgorithm() {
+		if ((layoutAlgorithm != null) && !layoutAlgorithm.isRunning()) {
+			this.removeThread(layoutThread);
+			this.addThread(layoutThread);
+		}
+	}
+	
+	/**	
+	 * Returns if the layout algorithm is running.
+	 * @return boolean if the layout algorithm is running
+	 */
+	public boolean isLayoutAlgorithmRunning() {
+		return ((layoutAlgorithm != null) && layoutAlgorithm.isRunning());
+	}
+	
+	/**	
+	 * Returns if the layout algorithm is paused.
+	 * @return boolean if the layout algorithm is paused
+	 */
+	public boolean isLayoutAlgorithmPaused() {
+		return ((layoutAlgorithm != null) && layoutAlgorithm.isPaused());
+	}
+	
+	
+	public void zoomIn() {
+		((GraphRootEditPart)this.getRootEditPart()).getZoomManager().zoomIn();
+	}
+	
+	public void zoomOut() {
+		((GraphRootEditPart)this.getRootEditPart()).getZoomManager().zoomOut();		
+	}
+	
+	
+	/**
+	 * Ensures that the selected node is visible (centered).
+	 * @see org.eclipse.gef.editparts.ZoomListener#zoomChanged(double)
+	 */
+	public void zoomChanged(double zoom) {
+		
+		Dimension dim = getCanvasSize();
+		if ((zoom < 1D) && (zoom > 0D)) {
+			layoutAlgorithm.setLayoutArea(10, 10, Math.max(0, (dim.width / zoom) - 10), Math.max(0, (dim.height / zoom) - 10));
+		} else {
+			layoutAlgorithm.setLayoutArea(10, 10, dim.width, dim.height);
+		}
+		
+		List selection = getSelectedEditParts();
+		if (selection.size() > 0) {
+			Object obj = selection.get(0);
+			if (obj instanceof GraphNodeEditPart) {
+				//GraphNodeEditPart editPart = (GraphNodeEditPart)obj;
+				//centerNodeInCanvas(editPart.getCastedModel());
+			}
+		}
+	}
+		
+	class _selectionChangedListener implements ISelectionChangedListener {
+		public void selectionChanged(SelectionChangedEvent event) {
+			//DebugPrint.println("Impl selection changed called: ");
+			Event e = new Event();
+			ArrayList selectedModelElements = new ArrayList( getSelectedEditParts().size() );
+			for ( Iterator iterator = getSelectedEditParts().iterator(); iterator.hasNext(); ) {
+				Object modelElement = ((EditPart) iterator.next()).getModel();
+				//DebugPrint.println(modelElement);
+				
+				selectedModelElements.add( modelElement );
+			}
+			e.data = new String("test");
+			
+			getControl().notifyListeners(SWT.Selection, null);
+		}
+	}
+	
+	public LayoutAlgorithm getLayoutAlgorithm() {
+		return layoutAlgorithm;
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/StaticGraphViewerImpl.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/StaticGraphViewerImpl.java
new file mode 100644
index 0000000..86f3f4d
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/StaticGraphViewerImpl.java
@@ -0,0 +1,428 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.draw2d.Animation;
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.gef.EditPart;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.core.internal.gefx.IPanningListener;
+import org.eclipse.mylar.zest.core.internal.gefx.NonThreadedGraphicalViewer;
+import org.eclipse.mylar.zest.core.internal.gefx.RevealListener;
+import org.eclipse.mylar.zest.core.internal.gefx.StaticGraphRootEditPart;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphItem;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IZestGraphDefaults;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphEditPartFactory;
+import org.eclipse.mylar.zest.core.internal.viewers.NoOverlapLayoutAlgorithm;
+import org.eclipse.mylar.zest.layouts.InvalidLayoutConfiguration;
+import org.eclipse.mylar.zest.layouts.LayoutAlgorithm;
+import org.eclipse.mylar.zest.layouts.LayoutStyles;
+import org.eclipse.mylar.zest.layouts.algorithms.GridLayoutAlgorithm;
+import org.eclipse.mylar.zest.layouts.algorithms.RadialLayoutAlgorithm;
+import org.eclipse.mylar.zest.layouts.algorithms.SpringLayoutAlgorithm;
+import org.eclipse.mylar.zest.layouts.algorithms.TreeLayoutAlgorithm;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * 
+ * @author Ian Bull
+ * @author Chris Callendar
+ */
+public class StaticGraphViewerImpl extends NonThreadedGraphicalViewer implements IPanningListener {
+	
+	private static final int ANIMATION_TIME = 500;
+	private LayoutAlgorithm layoutAlgorithm = null;
+	private NoOverlapLayoutAlgorithm noOverlapAlgorithm = null;
+	private GraphModel model = null;
+	private boolean allowMarqueeSelection = false;
+	private boolean allowPanning = false;
+	private boolean noOverlappingNodes = false;
+	private int style = 0;
+	private int nodeStyle;
+	private int connectionStyle;
+	private Dimension preferredSize = new Dimension(-1, -1);
+
+	private boolean hasLayoutRun = false;
+
+	
+	/**
+	 * Initializes the viewer impl. 
+	 * @see ZestStyles#PANNING
+	 * @see ZestStyles#NO_OVERLAPPING_NODES
+	 * @see ZestStyles#NODES_HIGHLIGHT_ADJACENT
+	 * @see ZestStyles#DIRECTED_GRAPH
+	 * @see ZestStyles#LAYOUT_GRID
+	 * @see ZestStyles#LAYOUT_TREE
+	 * @see ZestStyles#LAYOUT_RADIAL
+	 * @see ZestStyles#LAYOUT_SPRING
+	 * @see SWT#V_SCROLL
+	 * @see SWT#H_SCROLL
+	 */
+	public StaticGraphViewerImpl(Composite composite, int style) {
+		super(composite);
+		this.setStyle(style);
+		setConnectionStyle(IZestGraphDefaults.CONNECTION_STYLE);
+		setNodeStyle(IZestGraphDefaults.NODE_STYLE);
+		this.noOverlapAlgorithm = new NoOverlapLayoutAlgorithm();
+		this.setSelectionManager(new ZestSelectionManager());
+	}
+	
+	public boolean hasLayoutRun() {
+		return hasLayoutRun;
+	}
+	
+	/**
+	 * Gets the style on the SpringGraphViewer
+	 * @return int
+	 */
+	public int getStyle() {
+		return this.style;
+	}
+	
+	/**
+	 * Sets the scale for the main canvas
+	 * @param x The scale in the X direction
+	 * @param y The scale in the y direction
+	 */
+	public void setScale( double x, double y ) {
+		StaticGraphRootEditPart root = (StaticGraphRootEditPart)getRootEditPart();
+		root.setScale(x, y);
+		
+	}
+	
+	/**
+	 * Gets the scale in the y Direction
+	 */
+	public double getHeightScale() {
+		StaticGraphRootEditPart root = (StaticGraphRootEditPart)getRootEditPart();
+		return root.getYScale();
+	}
+	
+	/**
+	 * Gets the scale in the X Direction
+	 */
+	public double getWidthScale() {
+		StaticGraphRootEditPart root = (StaticGraphRootEditPart)getRootEditPart();
+		return root.getXScale();
+	}
+
+
+	/**
+	 * Sets the style for the viewer.
+	 * @param style
+	 */
+	public void setStyle(int style) {
+		this.style = style;
+		this.noOverlappingNodes = ZestStyles.checkStyle(style, ZestStyles.NO_OVERLAPPING_NODES);
+		this.allowPanning = ZestStyles.checkStyle(style, ZestStyles.PANNING);
+		this.allowMarqueeSelection = !allowPanning && ZestStyles.checkStyle(style, ZestStyles.MARQUEE_SELECTION);				
+		(getFigureCanvas()).setScrollBarVisibility(FigureCanvas.AUTOMATIC);
+		setLayoutAlgorithm(new GridLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING), false);
+	}
+	
+	/**
+	 * Sets the default connection style.
+	 * @param connection style the connection style to set
+	 * @see org.eclipse.mylar.zest.core.ZestStyles
+	 */
+	public void setConnectionStyle(int connectionStyle) {
+		this.connectionStyle = connectionStyle;
+		if (model != null) {
+			model.setConnectionStyle(connectionStyle);
+		}
+	}
+	
+	/**
+	 * Gets the default connection style.
+	 * @return the connection style
+	 * @see org.eclipse.mylar.zest.core.ZestStyles
+	 */
+	public int getConnectionStyle() {
+		return connectionStyle;
+	}
+	
+	/**
+	 * Sets the default node style.
+	 * @param nodeStyle the node style to set
+	 * @see org.eclipse.mylar.zest.core.ZestStyles
+	 */
+	public void setNodeStyle(int nodeStyle) {
+		this.nodeStyle = nodeStyle;
+		if (model != null) {
+			model.setNodeStyle(nodeStyle);
+		}
+	}
+	
+	/**
+	 * Gets the default node style.
+	 * @return the node style
+	 * @see org.eclipse.mylar.zest.core.ZestStyles
+	 */
+	public int getNodeStyle() {
+		return nodeStyle;
+	}
+	
+	/**
+	 * Sets the preferred size of the layout area. Size of ( -1, -1) uses the current canvas size.  
+	 * @param width
+	 * @param height
+	 */
+	public void setPreferredSize(int width, int height) {
+		
+		this.preferredSize = new Dimension(width, height);
+	}
+	
+
+	/**
+	 * Sets the model and initializes the layout algorithm.
+	 * @see org.eclipse.mylar.zest.core.internal.gefx.ThreadedGraphicalViewer#setContents(java.lang.Object)
+	 */
+	//@tag zest.bug.160367-Refreshing.fix : uses the IStylingGraphModelFactory now
+	public void setContents(Object model) { 
+		super.setContents( model );
+		this.model = (GraphModel)model;
+		applyLayout();
+	}
+	
+
+	/**
+	 * Runs the layout on this graph.
+	 * It uses the reveal listner to run the layout only if the view
+	 * is visible.  Otherwise it will be deferred until after the view
+	 * is available.
+	 */
+	public void applyLayout() {
+		this.addRevealListener(new RevealListener() {
+			public void revealed(Control c) {
+				PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+
+					public void run() {
+						applyLayoutInternal();
+					}
+				});
+			}
+		});
+	}
+	
+
+	
+	private void applyLayoutInternal() {		
+		
+		if ((model == null) || (model.getNodes().size() == 0)) 
+			return;
+		
+		if (layoutAlgorithm == null) {
+			layoutAlgorithm = new TreeLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
+		}
+		
+		// calculate the size for the layout algorithm
+		Dimension d = this.getCanvasSize();
+		Dimension nodeSize = findBiggestNode();
+		d.width = Math.max(0, d.width - nodeSize.width);
+		//@tag zest.bug.159645 : should be d.height - nodeSize.height
+		d.height = Math.max(0, d.height - nodeSize.height);
+		
+		if ( this.preferredSize.width >= 0 ) {
+			d.width = preferredSize.width;
+		}
+		if ( this.preferredSize.height >= 0 ) {
+			d.height = preferredSize.height;
+		}
+		
+		if (d.isEmpty())
+			return;
+		IGraphModelConnection[] connectionsToLayout = getConnectionsToLayout();
+		IGraphModelNode[] nodesToLayout = getNodesToLayout();
+		// For the spring layout, I think it works a little nicer 
+		// if a radial layout is run first first
+		if (layoutAlgorithm instanceof SpringLayoutAlgorithm) {
+			
+			try {
+				RadialLayoutAlgorithm radial = new RadialLayoutAlgorithm(LayoutStyles.NO_LAYOUT_NODE_RESIZING);
+				radial.applyLayout(nodesToLayout, connectionsToLayout, 0, 0, d.width, d.height, false, false);
+			} catch (InvalidLayoutConfiguration e) {
+				e.printStackTrace();
+			}
+			
+		}
+
+		try {
+			Animation.markBegin();
+			layoutAlgorithm.applyLayout(nodesToLayout, connectionsToLayout, 0, 0, d.width, d.height, false, false);
+			Animation.run(ANIMATION_TIME);
+			getLightweightSystem().getUpdateManager().performUpdate();
+			
+		} catch (InvalidLayoutConfiguration e) {
+			e.printStackTrace();
+		}
+
+		// enforce no overlapping nodes
+		if (noOverlappingNodes) {
+			noOverlapAlgorithm.layout(model.getNodes());
+		}
+		
+		hasLayoutRun = true;
+	}
+	
+	IGraphModelConnection[] getConnectionsToLayout() {
+//		@tag zest.bug.156528-Filters.follows : make sure not to layout filtered connections, if the style says so.
+		IGraphModelConnection[] entities;
+		if (ZestStyles.checkStyle(style, ZestStyles.IGNORE_INVISIBLE_LAYOUT)) {
+			LinkedList nodeList = new LinkedList();
+			for (Iterator i = model.getConnections().iterator(); i.hasNext();) {
+				IGraphItem next = (IGraphItem) i.next();
+				if (next.isVisible())
+					nodeList.add(next);
+			}
+			entities = (IGraphModelConnection[]) nodeList.toArray(new IGraphModelConnection[]{});
+		} else {
+			entities = model.getConnectionsArray();
+		}
+		return entities;
+	}
+	
+	IGraphModelNode[] getNodesToLayout(){
+//		@tag zest.bug.156528-Filters.follows : make sure not to layout filtered nodes, if the style says so.
+		IGraphModelNode[] entities;
+		if (ZestStyles.checkStyle(style, ZestStyles.IGNORE_INVISIBLE_LAYOUT)) {
+			LinkedList nodeList = new LinkedList();
+			for (Iterator i = model.getNodes().iterator(); i.hasNext();) {
+				IGraphItem next = (IGraphItem) i.next();
+				if (next.isVisible())
+					nodeList.add(next);
+			}
+			entities = (IGraphModelNode[]) nodeList.toArray(new IGraphModelNode[]{});
+		} else {
+			entities = model.getNodesArray();
+		}
+		return entities;
+	}
+	
+	private Dimension findBiggestNode() {
+		Dimension dim = new Dimension();
+		if (model != null) {
+			for (Iterator iter = model.getNodes().iterator(); iter.hasNext(); ) {
+				IGraphModelNode node = (IGraphModelNode)iter.next();
+				dim.width = Math.max(dim.width, (int)node.getWidthInLayout());
+				dim.height = Math.max(dim.height, (int)node.getHeightInLayout());
+			}
+		}
+		return dim;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.ui.parts.GraphicalViewerImpl#createDefaultRoot()
+	 */
+	//@tag zest.bug.156617ClearViewer.fix : create the correct default root.
+	protected void createDefaultRoot() {
+		StaticGraphRootEditPart root = new StaticGraphRootEditPart();
+		this.setRootEditPart(root);
+	}
+	
+//	@tag zest.bug.156617ClearViewer.fix : convenience.
+	private StaticGraphRootEditPart getCastedRoot() {
+		return (StaticGraphRootEditPart)getRootEditPart();
+	}
+	
+	protected void configureGraphicalViewer() {
+		//@tag zest.bug.156617ClearViewer.fix : just clear the children, don't create a new root.
+		getCastedRoot().clear();
+		getCastedRoot().configure(this, allowMarqueeSelection, allowPanning);
+		this.setEditPartFactory(new GraphEditPartFactory(getCastedRoot()));
+	}
+
+	public void panningStart() {
+	}
+
+	public void panning(int dx, int dy) {
+			// @tag zest(bug(153356)) : Revist panning support for static graph
+	   	//((AbstractLayoutAlgorithm)layoutAlgorithm).moveAllEntities(dx, dy);
+	}
+
+	public void panningEnd() {
+	}
+
+	/**
+	 * @param algorithm
+	 */
+	public void setLayoutAlgorithm(LayoutAlgorithm algorithm, boolean applyLayout) {
+		this.layoutAlgorithm = algorithm;
+		if (applyLayout) {
+			applyLayout();
+		}
+	}
+
+
+	
+	/**
+	 * Updates the connection with the given weight.  
+	 * The weight should be in {-1, [0-1]}.  
+	 * A weight of -1 means that there is no force/tension between the nodes.
+	 * A weight of 0 results in the maximum spring length being used (farthest apart).
+	 * A weight of 1 results in the minimum spring length being used (closest together).
+	 * @param connection	The connection object.
+	 * @param weight		The new weight for the connection.
+	 */
+	public void updateRelationshipWeight(Object connection, double weight) {
+		IGraphModelConnection relationship = model.getInternalConnection(connection);
+		if (relationship != null) {
+			relationship.setWeightInLayout(weight);
+			applyLayout();
+		}
+	}
+
+
+	
+	public void setSelection(List selection) {
+		if (model == null) return;
+		Iterator iterator = selection.iterator();
+		HashMap nodeMap = model.getNodesMap();
+		HashMap connectionMap = model.getConnectionMap();
+		List editPartList = new ArrayList(1);
+		while (iterator.hasNext()) {
+			Object current = iterator.next();
+			Object currentNode = nodeMap.get(current);
+			if ( current != null ) {
+				//@tag zest(bug(153466-NoNestedClientSupply(fix))) : use the edit part registry to avoid having back-links in the model.
+				EditPart part = (EditPart) getEditPartRegistry().get(currentNode);
+				if (part != null)
+					editPartList.add(part);//((GraphModelNode)currentNode).getEditPart() );
+			}
+			else {
+				Object currentConnection = connectionMap.get(current);
+				if ( currentConnection != null ) {
+					// Currenly we cannot select edges
+				}
+			}
+		}
+		setSelection(new StructuredSelection(editPartList));
+	}
+	
+	public LayoutAlgorithm getLayoutAlgorithm() {
+		return layoutAlgorithm;
+	}
+	
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/ZestSelectionManager.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/ZestSelectionManager.java
new file mode 100644
index 0000000..7ee1297
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/ZestSelectionManager.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.gef.SelectionManager;
+import org.eclipse.gef.editparts.AbstractEditPart;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphItem;
+
+/**
+ * This Selection Manager converts edit parts to the user data type and returns
+ * those. If this were not here, Zest would return the Edit parts as selection
+ * and not what the user passed in through the content provider.
+ * 
+ * @author Ian Bull
+ * 
+ */
+public class ZestSelectionManager extends SelectionManager {
+	
+	/**
+	 * Gets a list of currently selected nodes.  The selection will include the "user objects"
+	 * that have been selected.
+	 * 
+	 * @return A List of user objects that has been selected.
+	 */
+	public List getSelectedModelElements() {
+		List selections = new ArrayList(1);
+		ISelection selection = super.getSelection();
+		
+		IStructuredSelection structuredSelection = (IStructuredSelection) selection;
+		Iterator elements = structuredSelection.iterator();
+		
+		// Loop through all selected elements and get the user data for these
+		while (elements.hasNext()) {
+			AbstractEditPart editPart = (AbstractEditPart) elements.next();
+			if (editPart.getModel() == null) {
+				return Collections.EMPTY_LIST;
+			}
+			else if (editPart.getModel() instanceof IGraphItem) {
+				IGraphItem item = (IGraphItem) editPart.getModel();
+				if (!(item instanceof GraphModel)) {
+					selections.add(item.getData());
+				}
+			}
+		}
+		return selections;
+	}
+	
+	/**
+	 * Gets the current selection in the Zest viewer as an ISelection.
+	 */
+	public ISelection getSelection() {
+		List selections = getSelectedModelElements();
+		if ( selections.size() == 0 ) return StructuredSelection.EMPTY;
+		return new StructuredSelection( selections );
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/GraphOverviewerImpl.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/GraphOverviewerImpl.java
new file mode 100644
index 0000000..717af84
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/GraphOverviewerImpl.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.overview;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditDomain;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.RootEditPart;
+import org.eclipse.gef.Tool;
+import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
+import org.eclipse.gef.editparts.ScalableRootEditPart;
+import org.eclipse.gef.editparts.ZoomManager;
+import org.eclipse.gef.ui.parts.DomainEventDispatcher;
+import org.eclipse.gef.ui.parts.GraphicalViewerImpl;
+import org.eclipse.mylar.zest.core.internal.gefx.IZestViewerProperties;
+import org.eclipse.mylar.zest.core.internal.graphviewer.overview.parts.OverviewEditPart;
+import org.eclipse.mylar.zest.core.internal.graphviewer.overview.parts.OverviewImageEditPartFactory;
+import org.eclipse.mylar.zest.core.internal.graphviewer.overview.parts.OverviewRootEditPart;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.tools.OverviewRectangleTool;
+import org.eclipse.swt.graphics.Cursor;
+
+/**
+ * A viewer that simply draws an "overview" graph of nodes only.
+ * @author Del Myers
+ *
+ */
+public class GraphOverviewerImpl extends GraphicalViewerImpl implements PropertyChangeListener  {
+
+			
+	private EditPartViewer model;
+
+	/**
+	 * 
+	 */
+	public GraphOverviewerImpl() {
+		setEditPartFactory(new OverviewImageEditPartFactory());
+		EditDomain domain = new EditDomain();
+		//ToolEventDispatcher dispatcher = new ToolEventDispatcher(this);
+		domain.setDefaultTool(new OverviewRectangleTool());
+		domain.setActiveTool(domain.getDefaultTool());
+		DomainEventDispatcher dispatcher = new DomainEventDispatcher(domain, this);
+		setEditDomain(domain);
+		//dispatcher.setTool(new OverviewRectangleTool());
+		getLightweightSystem().setEventDispatcher(dispatcher);
+	}
+	
+	protected void createDefaultRoot() {
+		ScalableRootEditPart root = new OverviewRootEditPart();
+		this.setRootEditPart(root);
+	}
+	
+	private ScalableRootEditPart getCastedRoot() {
+		return (ScalableRootEditPart)getRootEditPart();
+	}
+
+		
+	public void setContents(Object model) {
+		if (model instanceof EditPartViewer) {
+			EditPartViewer newModel = (EditPartViewer) model;
+			if (this.model != model) {
+				if (this.model != null) 
+					this.model.removePropertyChangeListener(this);
+				this.model = newModel;
+				super.setContents(newModel);
+				this.model.addPropertyChangeListener(this);
+				Tool tool = getEditDomain().getActiveTool();
+				if (tool instanceof OverviewRectangleTool) {
+					tool.setViewer(this);
+					((OverviewRectangleTool)tool).setZoomManager(getZoomManager(model));
+				}
+			} 
+		} else {
+			
+		}
+	}
+	
+	/**
+	 * @param model2
+	 * @return
+	 */
+	private ZoomManager getZoomManager(Object model) {
+		if (model instanceof EditPartViewer) {
+			RootEditPart modelRoot = ((EditPartViewer)model).getRootEditPart();
+			if (modelRoot instanceof ScalableFreeformRootEditPart) {
+				return ((ScalableFreeformRootEditPart)modelRoot).getZoomManager();
+			} else if (modelRoot instanceof ScalableRootEditPart) {
+				return ((ScalableRootEditPart)modelRoot).getZoomManager();
+			}
+		}
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.ui.parts.GraphicalViewerImpl#setCursor(org.eclipse.swt.graphics.Cursor)
+	 */
+	public void setCursor(Cursor newCursor) {
+		if (getControl() != null && !getControl().isDisposed()) {
+			getControl().setCursor(newCursor);
+		}
+	}
+	
+	public void setZoom(Rectangle zoom) {
+		OverviewEditPart content = (OverviewEditPart) getCastedRoot().getContents();
+		Rectangle copy = zoom.getCopy();
+		//((GraphicalEditPart)getRootEditPart()).getFigure().translateToRelative(copy);
+		if (content==null) return; //not yet initialized.
+		content.translateToViewer(copy);
+		RootEditPart modelRoot = this.model.getRootEditPart();
+		if (modelRoot instanceof ScalableFreeformRootEditPart) {
+			if (!zoom.isEmpty()) {
+			((ScalableFreeformRootEditPart)modelRoot).getZoomManager().zoomTo(copy);
+			} else {
+				//ensure that the rectangle has a zero width and height so that 
+				//it is centered and the view is not scaled.
+				copy.width = 0;
+				copy.height = 0;
+				((ScalableFreeformRootEditPart)modelRoot).getZoomManager().zoomTo(copy);
+			}
+		} else if (modelRoot instanceof ScalableRootEditPart) {
+			if (!zoom.isEmpty()) {
+				((ScalableRootEditPart)modelRoot).getZoomManager().zoomTo(copy);
+			} else {
+//				ensure that the rectangle has a zero width and height so that 
+				//it is centered and the view is not scaled.
+				copy.width = 0;
+				copy.height = 0;
+				((ScalableRootEditPart)modelRoot).getZoomManager().zoomTo(copy);
+			}
+		}
+	}
+
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.ui.parts.GraphicalViewerImpl#unhookControl()
+	 */
+	protected void unhookControl() {
+		Tool tool = getEditDomain().getActiveTool();
+		if (tool instanceof OverviewRectangleTool) {
+			((OverviewRectangleTool)tool).setZoomManager(null);
+		}
+		super.unhookControl();
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+	 */
+	public void propertyChange(PropertyChangeEvent evt) {
+		if (IZestViewerProperties.GRAPH_VIEWER_CONTENTS.equals(evt.getPropertyName())) {
+			//set the zoom to nothing.
+			//setZoom(new Rectangle());
+			//have to refresh the whole thing.
+			//super.setContents(this.model);
+		}
+	}
+	
+	
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/ToolEventDispatcher.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/ToolEventDispatcher.java
new file mode 100644
index 0000000..a01a29a
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/ToolEventDispatcher.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.overview;
+
+import org.eclipse.draw2d.InputEvent;
+import org.eclipse.draw2d.SWTEventDispatcher;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.Tool;
+import org.eclipse.gef.tools.SelectionTool;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.TraverseEvent;
+import org.eclipse.swt.widgets.Event;
+
+/**
+ * An event dispatcher that simply delegates events to tools.
+ * @author Del Myers
+ *
+ */
+public class ToolEventDispatcher extends SWTEventDispatcher {
+	private EditPartViewer viewer;
+	private Tool tool;
+
+	public ToolEventDispatcher(EditPartViewer viewer) {
+		this.viewer = viewer;
+		setTool(new SelectionTool());
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.SWTEventDispatcher#dispatchFocusGained(org.eclipse.swt.events.FocusEvent)
+	 */
+	public void dispatchFocusGained(FocusEvent e) {
+		tool.focusGained(e, viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.SWTEventDispatcher#dispatchFocusLost(org.eclipse.swt.events.FocusEvent)
+	 */
+	public void dispatchFocusLost(FocusEvent e) {
+		tool.focusLost(e, viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.SWTEventDispatcher#dispatchKeyPressed(org.eclipse.swt.events.KeyEvent)
+	 */
+	public void dispatchKeyPressed(KeyEvent e) {
+		tool.keyDown(e, viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.SWTEventDispatcher#dispatchKeyReleased(org.eclipse.swt.events.KeyEvent)
+	 */
+	public void dispatchKeyReleased(KeyEvent e) {
+		tool.keyUp(e, viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.SWTEventDispatcher#dispatchKeyTraversed(org.eclipse.swt.events.TraverseEvent)
+	 */
+	public void dispatchKeyTraversed(TraverseEvent e) {
+		tool.keyTraversed(e, viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMouseDoubleClicked(org.eclipse.swt.events.MouseEvent)
+	 */
+	public void dispatchMouseDoubleClicked(MouseEvent me) {
+		tool.mouseDoubleClick(me, viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMouseEntered(org.eclipse.swt.events.MouseEvent)
+	 */
+	public void dispatchMouseEntered(MouseEvent me) {
+		tool.viewerEntered(me, viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMouseExited(org.eclipse.swt.events.MouseEvent)
+	 */
+	public void dispatchMouseExited(MouseEvent me) {
+		tool.viewerExited(me, viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMouseHover(org.eclipse.swt.events.MouseEvent)
+	 */
+	public void dispatchMouseHover(MouseEvent me) {
+		tool.mouseHover(me, viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMouseMoved(org.eclipse.swt.events.MouseEvent)
+	 */
+	public void dispatchMouseMoved(MouseEvent me) {
+		if ((me.stateMask & InputEvent.ANY_BUTTON) != 0)
+			tool.mouseDrag(me, viewer);
+		else
+			tool.mouseMove(me, viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMousePressed(org.eclipse.swt.events.MouseEvent)
+	 */
+	public void dispatchMousePressed(MouseEvent me) {
+		tool.mouseDown(me, viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.SWTEventDispatcher#dispatchMouseReleased(org.eclipse.swt.events.MouseEvent)
+	 */
+	public void dispatchMouseReleased(MouseEvent me) {
+		tool.mouseUp(me, viewer);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.EventDispatcher#dispatchMouseWheelScrolled(org.eclipse.swt.widgets.Event)
+	 */
+	public void dispatchMouseWheelScrolled(Event event) {
+		tool.mouseWheelScrolled(event, viewer);
+	}
+	
+	public void setTool(Tool tool) {
+		this.tool = tool;
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewEditPart.java
new file mode 100644
index 0000000..df03579
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewEditPart.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.overview.parts;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.draw2d.FigureListener;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.XYLayout;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.policies.NullLayoutEditPolicy;
+
+/**
+ * 
+ * @author Del Myers
+ *
+ */
+public class OverviewEditPart extends AbstractGraphicalEditPart implements FigureListener {
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphEditPart#createEditPolicies()
+	 */
+	protected void createEditPolicies() {
+		installEditPolicy(EditPolicy.LAYOUT_ROLE, new NullLayoutEditPolicy());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
+	 */
+	protected IFigure createFigure() {
+		IFigure figure = new ScalingContainerFigure();
+		figure.setLayoutManager(new XYLayout());
+		return figure;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#activate()
+	 */
+	public void activate() {
+		GraphicalEditPart part = (GraphicalEditPart) getCastedModel().getRootEditPart();
+		IFigure parentPane = part.getFigure();
+		parentPane.addFigureListener(this);
+		//getFigure().addFigureListener(this);
+		super.activate();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#deactivate()
+	 */
+	public void deactivate() {
+		GraphicalEditPart part = (GraphicalEditPart) getCastedModel().getRootEditPart();
+		IFigure parentPane = part.getFigure();
+		parentPane.removeFigureListener(this);
+		//getFigure().removeFigureListener(this);
+		super.deactivate();
+	}
+	
+	private EditPartViewer getCastedModel() {
+		return (EditPartViewer)getModel();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#getModelChildren()
+	 */
+	protected List getModelChildren() {
+		GraphicalEditPart part = (GraphicalEditPart) getCastedModel().getRootEditPart();
+//		List children = part.getChildren();
+		List modelChildren = new LinkedList();
+		modelChildren.add(part);
+//		for (Iterator i = children.iterator(); i.hasNext();) {
+//			EditPart child = (EditPart) i.next();
+//			if (!(child instanceof ConnectionEditPart)) {
+//				if (child instanceof GraphicalEditPart) {
+//					modelChildren.add(child);
+//				}
+//			}
+//		}
+		return modelChildren;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals()
+	 */
+	protected void refreshVisuals() {
+		super.refreshVisuals();
+		
+		Rectangle boundingArea = getBoundingArea();
+		ScalingContainerFigure figure = (ScalingContainerFigure) getFigure();
+		
+		if (!figure.getLogicalBounds().equals(boundingArea)) {
+			figure.setLogicalBounds(boundingArea);
+		}
+		//figure.setBounds(boundingArea);
+		
+	}
+	/**
+	 * @return
+	 */
+	private Rectangle getBoundingArea() {
+		GraphicalEditPart part = (GraphicalEditPart) getCastedModel().getRootEditPart().getContents();
+ 		Rectangle boundingArea = null;
+		IFigure boundingFigure = part.getFigure();
+		for (Iterator i = boundingFigure.getChildren().iterator(); i.hasNext();) {
+			IFigure child = (IFigure) i.next();
+			if (boundingArea == null) {
+				boundingArea = child.getBounds().getCopy();
+			} else {
+				boundingArea.union(child.getBounds());
+			}
+		}
+		if (boundingArea == null) {
+			boundingArea = new Rectangle();
+		}
+		return boundingArea;
+	}
+
+	/**
+	 * Translates the rectangle given in absolute coordinates first into coordinates
+	 * that correspond to the coordinate system of this part's target viewer.
+	 * @param rect
+	 */
+	public void translateToViewer(Rectangle rect) {
+		getFigure().translateFromParent(rect);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.FigureListener#figureMoved(org.eclipse.draw2d.IFigure)
+	 */
+	public void figureMoved(IFigure source) {
+		refreshVisuals();
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewGraphEditPartFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewGraphEditPartFactory.java
new file mode 100644
index 0000000..e61b52a
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewGraphEditPartFactory.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.overview.parts;
+
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartFactory;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.GraphicalEditPart;
+
+
+/**
+ * Creates the edit parts associated with the different models.
+ * @deprecated
+ */
+public class OverviewGraphEditPartFactory implements EditPartFactory {
+	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.EditPartFactory#createEditPart(org.eclipse.gef.EditPart, java.lang.Object)
+	 */
+	public EditPart createEditPart(EditPart context, Object model) {
+		EditPart editPart = null;
+		if (model instanceof EditPartViewer) {
+			editPart = new OverviewEditPart();
+		} else if (model instanceof GraphicalEditPart) {
+			editPart = new OverviewNodeEditPart();
+		}
+		editPart.setModel(model);
+		
+		return editPart;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewImageEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewImageEditPart.java
new file mode 100644
index 0000000..db180a6
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewImageEditPart.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.overview.parts;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.ImageFigure;
+import org.eclipse.draw2d.SWTGraphics;
+import org.eclipse.draw2d.UpdateListener;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.RootEditPart;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * An edit part that links itself to a graphical root edit part, and periodically refreshes itself
+ * with the data in that edit part in order to create an overview.
+ * @author Del Myers
+ */
+
+public class OverviewImageEditPart extends AbstractGraphicalEditPart implements UpdateListener {
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
+	 */
+	Image image;
+	protected IFigure createFigure() {
+		ImageFigure figure = new ImageFigure();
+		return figure;
+	}
+
+	private GraphicalEditPart getCastedModel() {
+		return (GraphicalEditPart)getModel();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
+	 */
+	protected void createEditPolicies() {
+		// TODO Auto-generated method stub
+
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals()
+	 */
+	protected void refreshVisuals() {
+		
+		IFigure clientFigure = ((GraphicalEditPart)((RootEditPart)getCastedModel()).getContents()).getFigure();
+		Rectangle clientBounds = getBoundingArea();
+		if (clientBounds.isEmpty()) return;
+		if (image == null) {
+			image = new Image(Display.getDefault(), clientBounds.width, clientBounds.height);
+		}
+		Rectangle imageBounds = new Rectangle(image.getBounds().x, image.getBounds().y, image.getBounds().width, image.getBounds().height);
+		if (!imageBounds.getSize().equals(clientBounds.getSize())) {
+			if (!image.isDisposed()) {
+				image.dispose();
+			}
+			image = new Image(Display.getDefault(), clientBounds.width, clientBounds.height);
+		}
+		GC drawer = new GC(image);
+		SWTGraphics graphics = new SWTGraphics(drawer);
+		graphics.translate(-clientBounds.x, -clientBounds.y);
+		clientFigure.paint(graphics);
+		drawer.dispose();
+		getFigure().setBounds(clientBounds);
+		((ImageFigure)getFigure()).setImage(image);
+		getFigure().invalidate();
+		getFigure().repaint();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#activate()
+	 */
+	public void activate() {
+		getCastedModel().getFigure().getUpdateManager().addUpdateListener(this);
+		super.activate();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#deactivate()
+	 */
+	public void deactivate() {
+		getCastedModel().getFigure().getUpdateManager().removeUpdateListener(this);
+		super.deactivate();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#unregisterVisuals()
+	 */
+	protected void unregisterVisuals() {
+		if (image != null && !image.isDisposed()) {
+			image.dispose();
+			image = null;
+		}
+		super.unregisterVisuals();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.UpdateListener#notifyPainting(org.eclipse.draw2d.geometry.Rectangle, java.util.Map)
+	 */
+	public void notifyPainting(Rectangle damage, Map dirtyRegions) {
+		IFigure clientFigure = ((GraphicalEditPart)((RootEditPart)getCastedModel()).getContents()).getFigure();
+		Rectangle clientBounds = getBoundingArea();
+		if (clientBounds.isEmpty()) return;
+		if (image == null) {
+			refreshVisuals();
+			return;
+		}
+		Rectangle imageBounds = new Rectangle(image.getBounds().x, image.getBounds().y, image.getBounds().width, image.getBounds().height);
+		if (!imageBounds.getSize().equals(clientBounds.getSize())) {
+			refreshVisuals();
+			return;
+		}
+		List clientChildren = clientFigure.getChildren();
+		Iterator keys = clientChildren.iterator();
+		
+		Rectangle region = (Rectangle) dirtyRegions.get(clientFigure);
+		List dirtyFigures = new LinkedList();
+		if (region != null) {
+			dirtyFigures.add(clientFigure);
+		}
+		while (keys.hasNext()) {
+			IFigure fig = (IFigure) keys.next();
+			region = (Rectangle) dirtyRegions.get(fig);
+			if (region != null) {
+				dirtyFigures.add(fig);
+			}
+		}
+		if (dirtyFigures.size() > clientChildren.size()/2) {
+			refreshVisuals();
+			return;
+		}
+		calculateDirtyArea(clientFigure, dirtyFigures, dirtyRegions);
+	}
+	
+	/**
+	 * @return
+	 */
+	private Rectangle getBoundingArea() {
+		IFigure clientFigure = ((GraphicalEditPart)((RootEditPart)getCastedModel()).getContents()).getFigure();
+		//Dimension logicalSize = part.getFigure().getSize();
+ 		Rectangle boundingArea = null;//new Rectangle(new Point(0,0), logicalSize);
+		for (Iterator i = clientFigure.getChildren().iterator(); i.hasNext();) {
+			IFigure child = (IFigure) i.next();
+			if (boundingArea == null) {
+				boundingArea = child.getBounds().getCopy();
+			} else {
+				boundingArea.union(child.getBounds());
+			}
+		}
+		if (boundingArea == null) {
+			boundingArea = new Rectangle();
+		}
+//		boundingArea.width += Math.abs(boundingArea.x);
+//		boundingArea.height += Math.abs(boundingArea.y);
+//		boundingArea.x = 0;
+//		boundingArea.y = 0;
+		return boundingArea;
+	}
+
+	/**
+	 * @param dirtyFigures
+	 * @param dirtyRegions
+	 * @return
+	 */
+	private Rectangle calculateDirtyArea(IFigure clientFigure, List dirtyFigures, Map dirtyRegions) {
+		if (image == null) return null;
+//		if (region == null)
+//			return null;
+		GC drawer = new GC(image);
+		Graphics graphics = new SWTGraphics(drawer);
+		graphics.setBackgroundColor(clientFigure.getBackgroundColor());
+		Rectangle clientbounds = getBoundingArea();
+		graphics.translate(-clientbounds.x, -clientbounds.y);
+		for (Iterator dirty = dirtyFigures.iterator(); dirty.hasNext();) {
+			IFigure fig = (IFigure) dirty.next();
+			Rectangle r = ((Rectangle) dirtyRegions.get(fig)).getCopy();
+//			r.x -= fig.getInsets().left;
+//			r.y -= fig.getInsets().top;
+//			r.height += fig.getInsets().bottom;
+//			r.width += fig.getInsets().right;
+			
+			//fig.getParent().translateToAbsolute(r);
+			r = fig.getBounds().getCopy();
+			//r.expand(fig.getInsets());
+			graphics.fillRectangle(r);
+			fig.paint(graphics);
+			
+		
+//			intersectingSet.add(fig);
+//			region.union(r);
+//			for (Iterator intersectors = childSet.iterator(); intersectors.hasNext();) {
+//				IFigure intersect = (IFigure) intersectors.next();
+//				if (intersect.getBounds().intersects(region)) {
+//					region.union(intersect.getBounds());
+//					intersectingSet.add(intersect);
+//					intersectors.remove();
+//				}
+//			}
+		}
+//		graphics.fillRectangle(region);
+//		for (Iterator figs = intersectingSet.iterator(); figs.hasNext();) {
+//			((IFigure)figs.next()).paint(graphics);
+//		}
+		drawer.dispose();
+		getFigure().repaint();
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.UpdateListener#notifyValidating()
+	 */
+	public void notifyValidating() {
+		// TODO Auto-generated method stub
+		
+	}
+	
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewImageEditPartFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewImageEditPartFactory.java
new file mode 100644
index 0000000..1b44c4b
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewImageEditPartFactory.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.overview.parts;
+
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartFactory;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.GraphicalEditPart;
+
+
+/**
+ * Creates the edit parts associated with the different models.
+ * @author Chris Callendar
+ */
+public class OverviewImageEditPartFactory implements EditPartFactory {
+	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.EditPartFactory#createEditPart(org.eclipse.gef.EditPart, java.lang.Object)
+	 */
+	public EditPart createEditPart(EditPart context, Object model) {
+		EditPart editPart = null;
+		if (model instanceof EditPartViewer) {
+			editPart = new OverviewEditPart();
+		} else if (model instanceof GraphicalEditPart) {
+			editPart = new OverviewImageEditPart();
+		}
+		editPart.setModel(model);
+		
+		return editPart;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewNodeEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewNodeEditPart.java
new file mode 100644
index 0000000..ffc6efc
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewNodeEditPart.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.overview.parts;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+import org.eclipse.draw2d.FigureListener;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.RectangleFigure;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+
+/**
+ * A simple edit part that displays a rectangle representing a node.
+ * @author Del Myers
+ * @deprecated This class is going to be removed in future versions.
+ */
+public class OverviewNodeEditPart extends AbstractGraphicalEditPart implements FigureListener, PropertyChangeListener  {
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
+	 */
+	protected IFigure createFigure() {
+		Class clazz = getCastedModel().getClass();
+		InvocationHandler handler = new InvocationHandler() {
+			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+				return method.invoke(proxy, args);
+			}
+		};
+		try {
+			if (getCastedModel() instanceof AbstractGraphicalEditPart) {
+				Method setModel = clazz.getMethod("setModel", new Class[] {Object.class});
+				Object instance = clazz.newInstance();
+				setModel.invoke(instance, new Object[]{getCastedModel().getModel()});
+				Method method = AbstractGraphicalEditPart.class.getDeclaredMethod("getFigure", new Class[0]);
+				Object result = handler.invoke(instance, method, new Object[0]);
+				return (IFigure)result;
+			}
+		}  catch (Throwable e) {
+			//do nothing, just create a rectangle.
+		}
+		return new RectangleFigure();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#activate()
+	 */
+	public void activate() {
+		getCastedModel().getFigure().addFigureListener(this);
+		getCastedModel().getFigure().addPropertyChangeListener(this);
+		super.activate();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#deactivate()
+	 */
+	public void deactivate() {
+		getCastedModel().getFigure().removeFigureListener(this);
+		getCastedModel().getFigure().removePropertyChangeListener(this);
+		super.deactivate();
+	}
+	
+	//@tag zest.overview.todo : the model should actually be a proxy edit part that we can listen to figure changes on, that way our figures could look exactly the same.
+	private GraphicalEditPart getCastedModel() {
+		return (GraphicalEditPart)getModel();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
+	 */
+	protected void createEditPolicies() {
+	}
+
+		
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals()
+	 */
+	protected void refreshVisuals() {
+		super.refreshVisuals();
+		Rectangle bounds = getCastedModel().getFigure().getBounds().getCopy();
+		getFigure().setForegroundColor(getCastedModel().getFigure().getForegroundColor());
+		getFigure().setBackgroundColor(getCastedModel().getFigure().getBackgroundColor());
+		getFigure().getParent().setConstraint(getFigure(), bounds);
+		getParent().refresh();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.FigureListener#figureMoved(org.eclipse.draw2d.IFigure)
+	 */
+	public void figureMoved(IFigure source) {
+		refreshVisuals();
+	}
+
+	/* (non-Javadoc)
+	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+	 */
+	public void propertyChange(PropertyChangeEvent evt) {
+		refreshVisuals();
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewRootEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewRootEditPart.java
new file mode 100644
index 0000000..d99710f
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/OverviewRootEditPart.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.overview.parts;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.RangeModel;
+import org.eclipse.draw2d.StackLayout;
+import org.eclipse.draw2d.Viewport;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.DragTracker;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.editparts.ScalableRootEditPart;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.tools.OverviewRectangleTool;
+
+/**
+ * A simple root edit part that allows the viewport to be sized down.
+ * @author Del Myers
+ *
+ */
+public class OverviewRootEditPart extends ScalableRootEditPart {
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.ScalableRootEditPart#createFigure()
+	 */
+	protected IFigure createFigure() {
+		final Viewport figure = (Viewport) super.createFigure();
+		figure.setContentsTracksHeight(true);
+		figure.setContentsTracksWidth(true);
+		figure.getContents().setLayoutManager(new StackLayout(){
+			public Dimension getMinimumSize(IFigure container, int w, int h) {
+				return new Dimension(w,h);
+			}
+			/* (non-Javadoc)
+			 * @see org.eclipse.draw2d.StackLayout#layout(org.eclipse.draw2d.IFigure)
+			 */
+			public void layout(IFigure parent) {
+				List children = parent.getChildren();
+				RangeModel vertical = figure.getVerticalRangeModel();
+				RangeModel horizontal = figure.getHorizontalRangeModel();
+				for (Iterator i = children.iterator(); i.hasNext();) {
+					IFigure child = (IFigure) i.next();
+					child.setBounds(new Rectangle(0,0,horizontal.getMaximum(), vertical.getMaximum()));
+					
+				}
+			}
+		});
+		return figure;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.ScalableRootEditPart#getDragTracker(org.eclipse.gef.Request)
+	 */
+	public DragTracker getDragTracker(Request req) {
+		return new OverviewRectangleTool();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#getTargetEditPart(org.eclipse.gef.Request)
+	 */
+	public EditPart getTargetEditPart(Request request) {
+		return this;
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/ScalingContainerFigure.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/ScalingContainerFigure.java
new file mode 100644
index 0000000..05832a0
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/overview/parts/ScalingContainerFigure.java
@@ -0,0 +1,284 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.overview.parts;
+
+import java.util.List;
+
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.PrecisionDimension;
+import org.eclipse.draw2d.geometry.PrecisionPoint;
+import org.eclipse.draw2d.geometry.PrecisionRectangle;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.draw2d.geometry.Translatable;
+import org.eclipse.draw2d.text.CaretInfo;
+
+/**
+ * A figure that scales all of its children to always be within its bounds.
+ * @author Del Myers
+ *
+ */
+public class ScalingContainerFigure extends Figure {
+	private static final int DEFAULT_SIZE = 1000; //the "default" size used for scaling.
+	private Rectangle logicalBounds;
+	
+	/**
+	 * 
+	 */
+	public ScalingContainerFigure() {
+		setLogicalBounds(new Rectangle(0,0,DEFAULT_SIZE, DEFAULT_SIZE));
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#useLocalCoordinates()
+	 */
+	protected boolean useLocalCoordinates() {
+		return true;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#isCoordinateSystem()
+	 */
+	public boolean isCoordinateSystem() {
+		return true;
+	}
+
+	public double getWidthScale() {
+		Dimension size = getSize();
+		Dimension logicalSize = getLogicalSize();
+		double widthScale = size.width/(double)logicalSize.width;
+		return widthScale;
+	}
+	
+	public double getHeightScale() {
+		Dimension size = getSize();
+		Dimension logicalSize = getLogicalSize();
+		double heightScale = size.height/(double)logicalSize.height;
+		return heightScale;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#translateFromParent(org.eclipse.draw2d.geometry.Translatable)
+	 */
+	public void translateFromParent(Translatable t) {
+		super.translateFromParent(t);
+		Dimension size = getSize();
+		Dimension logicalSize = getLogicalSize();
+		double widthScale = size.width/(double)logicalSize.width;
+		double heightScale = size.height/(double)logicalSize.height;
+		
+		
+		if ( t instanceof PrecisionRectangle ) {
+			PrecisionRectangle r = (PrecisionRectangle)t;
+			r.preciseX *= 1/widthScale;
+			r.preciseY *= 1/heightScale;
+			r.preciseWidth *= 1/widthScale;
+			r.preciseHeight *= 1/heightScale;
+			r.updateInts();
+		}
+		else if ( t instanceof Rectangle ) {
+			Rectangle r = (Rectangle)t;
+			r.scale(1/widthScale, 1/heightScale);
+		}
+		else if ( t instanceof CaretInfo ) {
+			CaretInfo c = (CaretInfo)t;
+			c.performScale(1/heightScale);
+		}
+		else if ( t instanceof PrecisionDimension ) {
+			PrecisionDimension d = (PrecisionDimension)t;
+			d.preciseWidth *= 1/widthScale;
+			d.preciseHeight *= 1/heightScale;
+			d.updateInts();
+		}
+		else if ( t instanceof Dimension ) {
+			Dimension d = (Dimension) t;
+			d.scale(1/widthScale, 1/heightScale);
+		}
+		else if ( t instanceof PrecisionPoint ) {
+			PrecisionPoint p = (PrecisionPoint) t;
+			p.preciseX *= 1/widthScale;
+			p.preciseY *= 1/heightScale;
+			p.updateInts();
+		}
+		else if ( t instanceof Point ) {
+			Point p = (Point)t;
+			p.scale(1/widthScale, 1/heightScale);
+		}
+		else if ( t instanceof PointList ) {
+			throw new RuntimeException("PointList not supported in AspectRatioScale");
+		}
+		else {
+			throw new RuntimeException( t.toString() + " not supported in AspectRatioScale");
+		}
+		t.performTranslate((int)(getLogicalReference().x), (int)(getLogicalReference().y));
+		//t.performScale(1/widthScale);		
+	}
+	
+	/**
+	 * Sets the logical size to the given width and heigth. This will be used
+	 * to determine how children should be scaled.
+	 * @param w the logical width.
+	 * @param h the logical height.
+	 */
+	public final void setLogicalSize(int w, int h) {
+		setLogicalSize(new Dimension(w, h));
+	}
+	
+	/**
+	 * Sets the logical size to the given dimension. This will be used to determine
+	 * how the children should be scaled.
+	 * @param size the logical size.
+	 */
+	public void setLogicalSize(Dimension size) {
+		setLogicalBounds(new Rectangle(new Point(0,0), size));
+		invalidate();
+	}
+	
+	/**
+	 * Sets the logical size to the dimensions of the bounds, and allows for translation
+	 * based on the position of the given rectangle. The top-left corner of the rectangle
+	 * will be translated to 0,0 in this scaling container.
+	 * @param bounds
+	 */
+	public void setLogicalBounds(Rectangle bounds) {
+		this.logicalBounds = bounds.getCopy();
+		invalidate();
+	}
+	
+	/**
+	 * Returns the top-left reference point for the bounds of the figures contained within
+	 * this container.
+	 * @return the logical reference.
+	 */
+	public Point getLogicalReference() {
+		return logicalBounds.getTopLeft();
+	}
+	
+	/**
+	 * @return the logicalSize
+	 */
+	public final Dimension getLogicalSize() {
+		return logicalBounds.getSize();
+	}
+	
+	/**
+	 * @return the logicalBounds
+	 */
+	public Rectangle getLogicalBounds() {
+		return logicalBounds;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#setBounds(org.eclipse.draw2d.geometry.Rectangle)
+	 */
+	public void setBounds(Rectangle rect) {
+		super.setBounds(rect);
+	}
+	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#paintClientArea(org.eclipse.draw2d.Graphics)
+	 */
+	protected void paintClientArea(Graphics graphics) {
+		List children = getChildren();
+		if (children.isEmpty())
+			return;
+
+		boolean optimizeClip = getBorder() == null || getBorder().isOpaque();
+
+		if (useLocalCoordinates()) {
+			graphics.translate(
+				getBounds().x + getInsets().left,
+				getBounds().y + getInsets().top);
+			if (isCoordinateSystem()) {
+				graphics.scale((float)getWidthScale(), (float)getHeightScale());
+				graphics.translate(getLogicalReference().getNegated());
+			}
+			if (!optimizeClip)
+				graphics.clipRect(getClientArea(new Rectangle()));
+			graphics.pushState();
+			paintChildren(graphics);
+			graphics.popState();
+			graphics.restoreState();
+		} else {
+			if (optimizeClip)
+				paintChildren(graphics);
+			else {
+				graphics.clipRect(getClientArea(new Rectangle()));
+				graphics.pushState();
+				paintChildren(graphics);
+				graphics.popState();
+				graphics.restoreState();
+			}
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#translateToParent(org.eclipse.draw2d.geometry.Translatable)
+	 */
+	public void translateToParent(Translatable t) {
+		Dimension size = getBounds().getSize();
+		Dimension logicalSize = getLogicalSize();
+		double widthScale = size.width/(double)logicalSize.width;
+		double heightScale = size.height/(double)logicalSize.height;
+		t.performTranslate(-getLogicalReference().x, -getLogicalReference().y);
+		
+		if ( t instanceof PrecisionRectangle ) {
+			PrecisionRectangle r = (PrecisionRectangle)t;
+			r.preciseX *= widthScale;
+			r.preciseY *= heightScale;
+			r.preciseWidth *= widthScale;
+			r.preciseHeight *= heightScale;
+			r.updateInts();
+		}
+		else if ( t instanceof Rectangle ) {
+			Rectangle r = (Rectangle)t;
+			//r.performScale(widthScale);
+			r.scale(widthScale, heightScale);
+		}
+		else if ( t instanceof CaretInfo ) {
+			CaretInfo c = (CaretInfo)t;
+			c.performScale(heightScale);
+		}
+		else if ( t instanceof PrecisionDimension ) {
+			PrecisionDimension d = (PrecisionDimension)t;
+			d.preciseWidth *= widthScale;
+			d.preciseHeight *= heightScale;
+			d.updateInts();
+		}
+		else if ( t instanceof Dimension ) {
+			Dimension d = (Dimension) t;
+			d.scale(widthScale, heightScale);
+		}
+		else if ( t instanceof PrecisionPoint ) {
+			PrecisionPoint p = (PrecisionPoint) t;
+			p.preciseX *= widthScale;
+			p.preciseY *= heightScale;
+			p.updateInts();
+		}
+		else if ( t instanceof Point ) {
+			Point p = (Point)t;
+			p.scale(widthScale, heightScale);
+		}
+		else if ( t instanceof PointList ) {
+			throw new RuntimeException("PointList not supported in AspectRatioScale");
+		}
+		else {
+			throw new RuntimeException( t.toString() + " not supported in AspectRatioScale");
+		}
+		
+		
+		super.translateToParent(t);
+		
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/GraphConnectionEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/GraphConnectionEditPart.java
new file mode 100644
index 0000000..b442959
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/GraphConnectionEditPart.java
@@ -0,0 +1,400 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.parts;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Label;
+import org.eclipse.draw2d.PolygonDecoration;
+import org.eclipse.draw2d.PolylineConnection;
+import org.eclipse.draw2d.PolylineDecoration;
+import org.eclipse.draw2d.RotatableDecoration;
+import org.eclipse.draw2d.Shape;
+import org.eclipse.gef.DragTracker;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.editparts.AbstractConnectionEditPart;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.core.internal.gefx.AligningBendpointLocator;
+import org.eclipse.mylar.zest.core.internal.gefx.BezierConnection;
+import org.eclipse.mylar.zest.core.internal.gefx.GraphRootEditPart;
+import org.eclipse.mylar.zest.core.internal.gefx.PolylineArcConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphItem;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelConnection;
+import org.eclipse.mylar.zest.core.internal.graphviewer.policies.HighlightConnectionEndpointEditPolicy;
+import org.eclipse.mylar.zest.core.internal.viewers.trackers.SingleSelectionTracker;
+
+
+/**
+ * @author Chris Callendar
+ */
+public class GraphConnectionEditPart extends AbstractConnectionEditPart implements PropertyChangeListener {
+	private RotatableDecoration dec;
+
+
+	/**
+	 * The constraint placed on the label for its alignment.
+	 */
+	//@tag zest.bug.160368-ConnectionAlign.fix
+	/**
+	 * 
+	 */
+	public GraphConnectionEditPart() {
+		super();
+	}
+
+	
+	
+
+	/**
+	 * Upon activation, attach to the model element as a property change listener.
+	 */
+	public void activate() {
+		if (!isActive()) {
+			super.activate();
+			((IGraphItem)getModel()).addPropertyChangeListener(this);
+		}
+	}
+
+	
+	/**
+	 * Upon deactivation, detach from the model element as a property change listener.
+	 */
+	public void deactivate() {
+		if (isActive()) {
+			super.deactivate();
+			((IGraphItem) getModel()).removePropertyChangeListener(this);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractConnectionEditPart#removeNotify()
+	 */
+	public void removeNotify() {
+		//disconnect
+
+		IFigure edge = getFigure();
+		IFigure layer = getLayer(CONNECTION_LAYER);
+		if (layer != null) {
+			if (edge.getParent() != layer) {
+				edge.getParent().remove(edge);
+				layer.add(edge);
+			}
+		}
+		super.removeNotify();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
+	 */
+	protected void createEditPolicies() {
+		installEditPolicy(EditPolicy.CONNECTION_ENDPOINTS_ROLE, new HighlightConnectionEndpointEditPolicy());
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
+	 */
+	protected IFigure createFigure() {
+		Connection connection;
+		IGraphModelConnection model = getCastedModel();
+		int connectionStyle = model.getConnectionStyle();
+		
+		//styles should have been set by the GraphItemStyler by this point.
+		if (model.getSource() == model.getDestination()) {
+			//@tag zest(bug(152180-SelfLoops)) : create an arc connection, despite the styles that have been set.
+			//allow for a self-loop.
+			//@tag zest(bug(154391-ArcEnds(fix))) :use a polyline arc connection
+			connection = new PolylineArcConnection();
+			if (model.getCurveDepth() <= 0) {
+				//it has to have a curve.
+				((PolylineArcConnection)connection).setDepth(10);
+			} else {
+				((PolylineArcConnection)connection).setDepth(model.getCurveDepth());
+			}
+		} else 	if (ZestStyles.checkStyle(connectionStyle, ZestStyles.CONNECTIONS_CURVED)) {
+			connection = new PolylineArcConnection();
+			((PolylineArcConnection)connection).setDepth(getCastedModel().getCurveDepth());
+		} else if (ZestStyles.checkStyle(connectionStyle, ZestStyles.CONNECTIONS_BEZIER)) {
+			connection = new BezierConnection(model.getStartAngle(), model.getStartLength(), model.getEndAngle(), model.getEndLength());
+		} else {
+			connection = (PolylineConnection)super.createFigure();
+		} 
+		connection.setForegroundColor(getCastedModel().getLineColor());
+		if (connection instanceof Shape) {
+			((Shape)connection).setLineWidth(getCastedModel().getLineWidth());
+			((Shape)connection).setLineStyle(getCastedModel().getLineStyle());
+		}
+		
+	  	AligningBendpointLocator labelLocator = new AligningBendpointLocator(connection);
+	  	if ( getCastedModel().getText() != null ||
+	  		getCastedModel().getImage() != null ) {
+	  		Label l = new Label(getCastedModel().getText(), getCastedModel().getImage());
+	  		l.setFont(getCastedModel().getFont());
+	  		connection.add(l,labelLocator);
+	  	}
+		
+		return connection;
+	}
+	
+	/**
+	 * Gets the drag tracker for the edge.  This means only 1 edge can be selected
+	 * @tag Selection : this controls single edge selection
+	 */
+	public DragTracker getDragTracker(Request req) {
+		return new SingleSelectionTracker(this);
+	}
+	
+	/**
+     * 
+     */
+	public void highlightEdge() {
+		IFigure thisEdge = getFigure(); 
+		IFigure layer = getLayer(CONNECTION_LAYER);
+		IFigure feedbackLayer = getLayer(GraphRootEditPart.CONNECTION_FEEDBACK_LAYER );
+		if (thisEdge.getParent() == layer) {
+			layer.remove(thisEdge);
+			feedbackLayer.add(thisEdge);
+		}
+
+	}
+	
+	/**
+     * 
+     */
+	public void unHighlightEdge() {
+		IFigure thisEdge = getFigure(); 
+		IFigure layer = getLayer(CONNECTION_LAYER);
+		IFigure feedbackLayer = getLayer(GraphRootEditPart.CONNECTION_FEEDBACK_LAYER );
+		if (thisEdge.getParent() == feedbackLayer) {
+			feedbackLayer.remove(thisEdge);
+			layer.add(thisEdge);
+		}
+
+	}
+	
+	/**
+	 * Gets the model casted into a GraphModelConnection
+	 * @return the model casted into a GraphModelConnection
+	 */
+	protected IGraphModelConnection getCastedModel() {
+		return (IGraphModelConnection)getModel();
+	}
+
+	/* (non-Javadoc)
+	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+	 */
+	public void propertyChange(PropertyChangeEvent event) {
+	
+		String property = event.getPropertyName();
+		IFigure figure = getFigure();
+		if (IGraphModelConnection.HIGHLIGHT_PROP.equals(property)) {
+			//@tag unreported(EdgeHighlight) : respond to model highlight changes.
+			highlightEdge();
+		} else	if (IGraphModelConnection.UNHIGHLIGHT_PROP.equals(property)) { 
+//			@tag unreported(EdgeHighlight) : respond to model highlight changes.
+			unHighlightEdge();
+		} else if (IGraphModelConnection.LINECOLOR_PROP.equals(property)) {
+			figure.setForegroundColor(getCastedModel().getLineColor());
+		} else if (IGraphModelConnection.LINEWIDTH_PROP.equals(property)) {
+			if (figure instanceof Shape)
+				((Shape)figure).setLineWidth(getCastedModel().getLineWidth());
+			RotatableDecoration dec = getDecoration();
+			if (dec instanceof PolylineDecoration) {
+				((PolylineDecoration)dec).setScale(getCastedModel().getLineWidth()+2, getCastedModel().getLineWidth()+2);
+			} else if (dec instanceof PolygonDecoration) {
+				((PolygonDecoration)dec).setScale(getCastedModel().getLineWidth()+2, getCastedModel().getLineWidth()+2);
+			} else if (dec instanceof Shape) {
+				((Shape)dec).setLineWidth(getCastedModel().getLineWidth());
+			}
+		} else if (IGraphModelConnection.LINESTYLE_PROP.equals(property)) {
+			if (figure instanceof Shape)
+				((Shape)figure).setLineStyle(getCastedModel().getLineStyle());
+		} else if (IGraphModelConnection.DIRECTED_EDGE_PROP.equals( property )) {
+		  	boolean directed = isDirected();
+		  	if (figure instanceof PolylineConnection) {
+		  		if (directed) {
+		  			((PolylineConnection)figure).setTargetDecoration(new PolygonDecoration());
+		  		}
+		  		else {
+		  			((PolylineConnection)figure).setTargetDecoration( null );
+		  		}
+		  	} else if (figure instanceof PolylineArcConnection) {
+				if (directed) {
+					((PolylineArcConnection)getFigure()).setTargetDecoration(new PolygonDecoration());
+				}
+				else {
+					((PolylineArcConnection)getFigure()).setTargetDecoration( null );
+				}
+			} else if (figure instanceof BezierConnection) {
+				if (directed) {
+		  			((BezierConnection)figure).setTargetDecoration(new PolygonDecoration());
+		  		}
+		  		else {
+		  			((BezierConnection)figure).setTargetDecoration( null );
+		  		}
+			}
+		} else if (IGraphItem.VISIBLE_PROP.equals(property)) {
+			getFigure().setVisible(((Boolean)event.getNewValue()).booleanValue());
+		} else if (IGraphModelConnection.CURVE_PROP.equals(property)) {
+			if (figure instanceof PolylineArcConnection) {
+				((PolylineArcConnection)figure).setDepth(getCastedModel().getCurveDepth());
+			} else if (figure instanceof BezierConnection) {
+				BezierConnection bezier = (BezierConnection) figure;
+				IGraphModelConnection conn = getCastedModel();
+				bezier.setStartAngle((int) Math.round(conn.getStartLength()));
+				bezier.setEndAngle((int) Math.round(conn.getEndAngle()));
+				bezier.setStartLength(conn.getStartLength());
+				bezier.setEndLength(conn.getEndLength());
+			}
+		}
+	}
+	
+	
+	/**
+	 * @return
+	 */
+	private boolean isDirected() {
+		int connectionStyle = getCastedModel().getConnectionStyle();
+		return ZestStyles.checkStyle(connectionStyle, ZestStyles.CONNECTIONS_DIRECTED);
+		
+	}
+
+	protected RotatableDecoration createDecoration() {
+		RotatableDecoration dec = new PolygonDecoration();
+		if (ZestStyles.checkStyle(getCastedModel().getConnectionStyle(), ZestStyles.CONNECTIONS_OPEN)) {
+			dec = new PolylineDecoration();
+			((PolylineDecoration)dec).setFill(false);
+			((PolylineDecoration)dec).setOutline(true);
+		}
+		return dec;
+	}
+	
+	public final RotatableDecoration getDecoration() {
+		if (dec == null) {
+			dec = createDecoration();
+			getFigure().add(dec);
+		}
+		return dec;
+	}
+	
+	protected void refreshVisuals() {
+		super.refreshVisuals();
+		IFigure figure = getFigure();
+		//@tag zest.bug.167128-EdgeVisibility : make the figue change visibility with model.
+		figure.setVisible(getCastedModel().isVisible());
+		figure.setForegroundColor(getCastedModel().getLineColor());
+		if (figure instanceof Shape) {
+			((Shape)figure).setLineWidth(getCastedModel().getLineWidth());
+			((Shape)figure).setLineStyle(getCastedModel().getLineStyle());
+		}
+		//@tag zest(bug(154595(fix))) : change the arrow size based on the line width.
+		boolean directed = isDirected();
+		RotatableDecoration dec = getDecoration();
+		if (dec instanceof PolylineDecoration) {
+			((PolylineDecoration)dec).setScale(getCastedModel().getLineWidth()+2, getCastedModel().getLineWidth()+2);
+		} else if (dec instanceof PolygonDecoration) {
+			((PolygonDecoration)dec).setScale(getCastedModel().getLineWidth()+2, getCastedModel().getLineWidth()+2);
+		} else if (dec instanceof Shape) {
+			((Shape)dec).setLineWidth(getCastedModel().getLineWidth());
+		}
+		if (figure instanceof PolylineArcConnection) {
+			if (directed) {
+				((PolylineArcConnection)getFigure()).setTargetDecoration(dec);
+			}
+			else {
+				((PolylineArcConnection)getFigure()).setTargetDecoration( null );
+			}
+			((PolylineArcConnection)figure).setDepth(getCastedModel().getCurveDepth());
+		} else if (figure instanceof BezierConnection) {
+			if (directed) {
+	  			((BezierConnection)figure).setTargetDecoration(dec);
+	  		}
+	  		else {
+	  			((BezierConnection)figure).setTargetDecoration( null );
+	  		}
+		} else if (figure instanceof PolylineConnection) { 	
+			if (directed) {
+				((PolylineConnection)getFigure()).setTargetDecoration(dec);
+			}
+			else {
+				((PolylineConnection)getFigure()).setTargetDecoration( null );
+			}
+		}
+		refreshLineStyle();
+		refreshLabelLocation();
+
+	}
+	/**
+	 * Refresh the alignment of labels.
+	 */
+	private void refreshLabelLocation() {
+		List children = getFigure().getChildren();
+		for (Iterator i = children.iterator(); i.hasNext();) {
+			IFigure child = (IFigure) i.next();
+			int style = getCastedModel().getConnectionStyle();
+			AligningBendpointLocator labelLocator = null;
+			try {
+				Object constraint = getFigure().getLayoutManager().getConstraint(child);
+				if (constraint instanceof AligningBendpointLocator) {
+					labelLocator = (AligningBendpointLocator)constraint;
+				}
+			} catch (Exception e) {
+				return;
+			}
+			if (labelLocator == null) return;
+			if (ZestStyles.checkStyle(style, ZestStyles.CONNECTIONS_VALIGN_TOP)) {
+				labelLocator.setVerticalAlginment(AligningBendpointLocator.ABOVE);
+			} else if (ZestStyles.checkStyle(style, ZestStyles.CONNECTIONS_VALIGN_BOTTOM)) {
+				labelLocator.setVerticalAlginment(AligningBendpointLocator.BELOW);
+			} else {
+				labelLocator.setVerticalAlginment(AligningBendpointLocator.MIDDLE);
+			}
+			if (ZestStyles.checkStyle(style, ZestStyles.CONNECTIONS_HALIGN_START)) {
+				labelLocator.setHorizontalAlignment(AligningBendpointLocator.BEGINNING);
+			} else if (ZestStyles.checkStyle(style, ZestStyles.CONNECTIONS_HALIGN_END)) {
+				labelLocator.setHorizontalAlignment(AligningBendpointLocator.END);
+			} else if (ZestStyles.checkStyle(style, ZestStyles.CONNECTIONS_HALIGN_CENTER_START)) {
+				labelLocator.setHorizontalAlignment(AligningBendpointLocator.CENTER_BEGINNING);
+			} else if (ZestStyles.checkStyle(style, ZestStyles.CONNECTIONS_HALIGN_CENTER_END)) {
+				labelLocator.setHorizontalAlignment(AligningBendpointLocator.CENTER_END);
+			} else {
+				labelLocator.setHorizontalAlignment(AligningBendpointLocator.CENTER);
+			}
+		}
+	}
+
+
+	/**
+	 * Refresh the line style for dashes, dots, etc.
+	 *
+	 */
+	private void refreshLineStyle() {
+		IFigure figure = getFigure();
+		int style = getCastedModel().getLineStyle();
+		if (figure instanceof Shape) {
+			((Shape)figure).setLineStyle(style);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#unregister()
+	 */
+	protected void unregister() {
+		// TODO Auto-generated method stub
+		super.unregister();
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/GraphEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/GraphEditPart.java
new file mode 100644
index 0000000..e921f60
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/GraphEditPart.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.parts;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.List;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.LayoutAnimator;
+import org.eclipse.draw2d.Viewport;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+import org.eclipse.gef.editparts.ZoomManager;
+import org.eclipse.gef.editpolicies.RootComponentEditPolicy;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphItem;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphviewer.policies.GraphXYLayoutEditPolicy;
+import org.eclipse.mylar.zest.core.internal.viewers.figures.AspectRatioFreeformLayer;
+
+
+/**
+ * The EditPart associated with the GraphModel.  The view creates a FreeformLayer figure.
+ *  
+ * @author Chris Callendar
+ */
+public class GraphEditPart extends AbstractGraphicalEditPart implements PropertyChangeListener {
+
+	//@tag zest.bug.156286-Zooming.fix : add a zoom manager to the edit part.
+	ZoomManager zoomer;
+	
+	public GraphEditPart() {
+		super();
+	}
+	
+	/**
+	 * Upon activation, attach to the model element as a property change listener.
+	 */
+	public void activate() {
+		if (!isActive()) {
+			super.activate();
+			((GraphItem) getModel()).addPropertyChangeListener(this);
+		}
+	}	
+	
+	/**
+	 * Upon deactivation, detach from the model element as a property change listener.
+	 */
+	public void deactivate() {
+		if (isActive()) {
+			super.deactivate();
+			((GraphItem) getModel()).removePropertyChangeListener(this);
+		}
+	}
+	
+	/**
+	 * Sets the scale for the graph
+	 * @param x
+	 * @param y
+	 */
+	public void setScale( double x, double y ) {
+		AspectRatioFreeformLayer aspectRatioFreeformLayer = (AspectRatioFreeformLayer) getFigure();
+		aspectRatioFreeformLayer.setScale( x, y );
+		//aspectRatioFreeformLayer.repaint();
+		getCastedModel().fireAllPropertyChange(IGraphModelNode.FORCE_REDRAW, null, null);	
+	}
+
+	/**
+	 * Gets the scale in the X Direction
+	 * @return
+	 */
+	public double getXScale() {
+		AspectRatioFreeformLayer aspectRatioFreeformLayer = (AspectRatioFreeformLayer) getFigure();
+		return aspectRatioFreeformLayer.getWidthScale();
+	}
+	
+	/**
+	 * Getes the scale in the Y Direction
+	 * @return
+	 */
+	public double getYScale() {
+		AspectRatioFreeformLayer aspectRatioFreeformLayer = (AspectRatioFreeformLayer) getFigure();
+		return aspectRatioFreeformLayer.getHeightScale();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
+	 */
+	protected IFigure createFigure() {
+		
+		AspectRatioFreeformLayer aspectRatioScaledFigure = new AspectRatioFreeformLayer("root");
+		aspectRatioScaledFigure.setScale(1.0, 1.0);
+		aspectRatioScaledFigure.addLayoutListener(LayoutAnimator.getDefault());
+		zoomer = new ZoomManager(aspectRatioScaledFigure, (Viewport)((GraphicalEditPart)getRoot()).getFigure());
+		return aspectRatioScaledFigure;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
+	 */
+	protected void createEditPolicies() {
+		// disallows the removal of this edit part from its parent
+		installEditPolicy(EditPolicy.COMPONENT_ROLE, new RootComponentEditPolicy());
+		installEditPolicy(EditPolicy.LAYOUT_ROLE,  new GraphXYLayoutEditPolicy());
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+	 */
+	public void propertyChange(PropertyChangeEvent evt) {
+		String prop = evt.getPropertyName();
+		// these properties are fired when Nodes and connections are added into or removed from 
+		// the LayoutDiagram instance and must cause a call of refreshChildren()
+		// to update the diagram's contents.
+		if (GraphModel.NODE_ADDED_PROP.equals(prop) || GraphModel.NODE_REMOVED_PROP.equals(prop)) {
+			refreshChildren();
+		} else if ( IGraphModelNode.HIGHLIGHT_PROP.equals( prop ) ) {
+			if (((Boolean)evt.getNewValue()).booleanValue()) {
+				setSelected(1);
+			} else {
+				setSelected(0);
+			}
+		}
+	}
+		
+	private GraphModel getCastedModel() {
+		return (GraphModel)getModel();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#getModelChildren()
+	 */
+	protected List getModelChildren() {
+		return getCastedModel().getNodes();
+	}	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#register()
+	 */
+	protected void register() {
+		super.register();
+		//@tag zest.bug.156286-Scaling.fix : set a property so that this can be zoomed on.
+		getViewer().setProperty(ZoomManager.class.toString(), getZoomManager());
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#unregister()
+	 */
+	protected void unregister() {
+		super.unregister();
+//		@tag zest.bug.156286-Scaling.fix : set a property so that this can be zoomed on.
+		getViewer().setProperty(ZoomManager.class.toString(), null);
+	}
+	
+	//@tag zest.bug.156286-Scaling.fix : get the zoom manager
+	public ZoomManager getZoomManager() {
+		return zoomer;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/GraphEditPartFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/GraphEditPartFactory.java
new file mode 100644
index 0000000..e7309bf
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/GraphEditPartFactory.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.parts;
+
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartFactory;
+import org.eclipse.mylar.zest.core.internal.gefx.ZestRootEditPart;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+
+
+/**
+ * Creates the edit parts associated with the different models.
+ * @author Chris Callendar
+ */
+public class GraphEditPartFactory implements EditPartFactory {
+	
+	protected ZestRootEditPart graphRootEditPart = null;
+	public GraphEditPartFactory( ZestRootEditPart graphRootEditPart ) {
+		this.graphRootEditPart = graphRootEditPart;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.EditPartFactory#createEditPart(org.eclipse.gef.EditPart, java.lang.Object)
+	 */
+	public EditPart createEditPart(EditPart context, Object model) {
+		EditPart editPart = null;
+		if (model instanceof IGraphModelNode) {
+			editPart = new GraphNodeEditPart();
+		} else if (model instanceof IGraphModelConnection) {
+			editPart = new GraphConnectionEditPart();
+		} else if (model instanceof GraphModel) {
+			editPart = new GraphEditPart();
+			graphRootEditPart.setModelRootEditPart( editPart );
+		} else {
+			throw new RuntimeException("Can't create part for model element: " + 
+					((model != null) ? model.getClass().getName() : "null"));
+		}
+		editPart.setModel(model);
+		
+		return editPart;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/GraphNodeEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/GraphNodeEditPart.java
new file mode 100644
index 0000000..52d0962
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/GraphNodeEditPart.java
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.parts;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.draw2d.ChopboxAnchor;
+import org.eclipse.draw2d.ConnectionAnchor;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Label;
+import org.eclipse.draw2d.LayoutAnimator;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.ConnectionEditPart;
+import org.eclipse.gef.DragTracker;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.NodeEditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphItem;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.viewers.figures.GraphLabel;
+import org.eclipse.mylar.zest.core.internal.viewers.figures.RoundedChopboxAnchor;
+import org.eclipse.mylar.zest.core.internal.viewers.trackers.SingleSelectionTracker;
+
+
+/**
+ * The edit part for the LayoutNode model.
+ * @author Chris Callendar
+ */
+public class GraphNodeEditPart extends AbstractGraphicalEditPart implements
+		PropertyChangeListener, NodeEditPart {
+	private Label toolTip;
+
+	protected ConnectionAnchor anchor;
+//	@tag zest(bug(152180-SelfLoops)) : New anchor required so that the loops aren't hidden by the node.
+	protected ConnectionAnchor loopAnchor;
+	/**
+	 * GraphNodeEditPart constructor.
+	 */
+	public GraphNodeEditPart() {
+		super();
+	}
+
+	/**
+	 * Upon activation, attach to the model element as a property change
+	 * listener.
+	 */
+	public void activate() {
+		if (!isActive()) {
+			super.activate();
+			((IGraphItem) getModel()).addPropertyChangeListener(this);
+		}
+	}
+
+	/**
+	 * Upon deactivation, detach from the model element as a property change
+	 * listener.
+	 */
+	public void deactivate() {
+		if (isActive()) {
+			super.deactivate();
+			((IGraphItem) getModel()).removePropertyChangeListener(this);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
+	 */
+	protected void createEditPolicies() {
+		// allow removal of the associated model element
+		// installEditPolicy(EditPolicy.COMPONENT_ROLE, new NodeComponentEditPolicy());
+		
+		// allow the creation of connections and the reconnection of connections between nodes
+		//installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new GraphNodeEditPolicy());
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
+	 */
+	protected IFigure createFigure() {
+		IFigure f = createFigureForModel();
+		f.addLayoutListener(LayoutAnimator.getDefault());
+		return f;
+	}
+
+	/**
+	 * Return a IFigure depending on the instance of the current model element.
+	 * This allows this EditPart to be used for both sublasses of Shape.
+	 */
+	protected IFigure createFigureForModel() {
+		IFigure figure;
+		if (getModel() instanceof IGraphModelNode) {
+			IGraphModelNode node = getCastedModel();
+			boolean cacheLabel = ((IGraphModelNode)getModel()).cacheLabel();
+			GraphLabel label = new GraphLabel(node.getText(), node.getImage(), cacheLabel);
+			label.setForegroundColor(node.getForegroundColor());
+			label.setBackgroundColor(node.getBackgroundColor());
+			label.setFont(node.getFont());
+			Dimension d = label.getSize();
+			node.setSizeInLayout(d.width, d.height);			
+			figure = label;
+			toolTip = new Label();
+			toolTip.setText(node.getText());
+			figure.setToolTip(toolTip);
+		} else {
+			// if Shapes gets extended the conditions above must be updated
+			throw new IllegalArgumentException("Unexpected model when creating a figure");
+		}
+		return figure;
+	}
+
+	/**
+	 * Gets a drag tracker which only allows one node to be selected at a time.
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getDragTracker(org.eclipse.gef.Request)
+	 */
+	public DragTracker getDragTracker(Request request) {
+		return new SingleSelectionTracker(this);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#performRequest(org.eclipse.gef.Request)
+	 */
+	public void performRequest(Request req) {
+		if (REQ_OPEN.equals(req.getType())) {
+			// TODO handle double-click
+		}
+		super.performRequest(req);
+	}
+
+//	@tag zest(bug(152180-SelfLoops)) : New anchor required so that the loops aren't hidden by the node.
+	protected ConnectionAnchor getLoopAnchor() {
+		if (loopAnchor == null) {
+			loopAnchor = new LoopAnchor(getFigure());
+		}
+		return loopAnchor;
+	}
+	
+//	@tag zest(bug(152180-SelfLoops)) : New anchor required so that the loops aren't hidden by the node.
+	protected ConnectionAnchor getDefaultConnectionAnchor() {
+		if (anchor == null) {
+			if (getModel() instanceof IGraphModelNode) {
+				IFigure figure = getFigure();
+				// use a rounded chopbox anchor for graph label figures (rounded corners)
+				if (figure instanceof GraphLabel) {
+					GraphLabel graphFigure = (GraphLabel) figure;
+					anchor = new RoundedChopboxAnchor(graphFigure, graphFigure.getArcWidth() / 2);
+				} else {
+					anchor = new ChopboxAnchor(figure);
+				}
+			} else {
+				throw new IllegalArgumentException("Unexpected model when creating an anchor");
+			}
+		}
+		return anchor;
+	}
+	
+		
+	/* (non-Javadoc)
+	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+	 */
+	public void propertyChange(PropertyChangeEvent evt) {
+		
+		
+		String prop = evt.getPropertyName();
+		if ( IGraphModelNode.FORCE_REDRAW.equals(prop)) {
+			refreshVisuals();
+			refreshChildren();
+			refreshColors();
+			getCastedModel().highlight();
+			getCastedModel().unhighlight();
+		}
+		else if (IGraphModelNode.LOCATION_PROP.equals(prop) || IGraphModelNode.SIZE_PROP.equals(prop)) {
+			refreshVisuals();
+		} else if (IGraphModelNode.SOURCE_CONNECTIONS_PROP.equals(prop)) {
+			refreshSourceConnections();
+		} else if (IGraphModelNode.TARGET_CONNECTIONS_PROP.equals(prop)) {
+			refreshTargetConnections();
+		} else if (IGraphModelNode.HIGHLIGHT_PROP.equals(prop)) {
+			refreshColors();
+		} else if (IGraphModelNode.COLOR_BG_PROP.equals(prop)) {
+			refreshColors();
+		} else if (IGraphModelNode.COLOR_FG_PROP.equals(prop)) {
+			refreshColors();
+		}
+		else if (IGraphModelNode.COLOR_BD_PROP.equals(prop)) {
+			refreshColors();
+		}
+		else if ( IGraphModelNode.BRING_TO_FRONT.equals(prop) ) {
+			IFigure figure = getFigure();
+			IFigure parent = figure.getParent();
+			parent.remove(figure);
+			parent.add(figure);
+			
+		} else if (IGraphItem.VISIBLE_PROP.equals(prop)) {
+			getFigure().setVisible(((Boolean)evt.getNewValue()).booleanValue());
+		}
+		
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals()
+	 */
+	protected void refreshVisuals() {
+		IGraphModelNode node = getCastedModel();
+		Point loc = node.getLocation();
+		Dimension size = node.getSize();
+		Rectangle bounds = new Rectangle(loc, size);
+		((GraphicalEditPart)getParent()).setLayoutConstraint(this, getFigure(), bounds);
+		refreshColors(); 
+	}
+
+	/**
+	 * Refreshes the figures colors from the model.  This includes the border color and width.
+	 */
+	protected void refreshColors() {
+		IFigure figure = getFigure();
+		IGraphModelNode model = getCastedModel();
+		figure.setForegroundColor(model.getForegroundColor());
+		figure.setBackgroundColor(model.getBackgroundColor());
+		
+		if (figure instanceof GraphLabel) {
+			GraphLabel label = (GraphLabel) figure;
+			label.setBorderColor(model.getBorderColor());
+			label.setBorderWidth(model.getBorderWidth());
+		}	
+	}
+	
+	/**
+	 * Returns the model casted into a GraphModelNode.
+	 * @return the casted GraphModelNode model
+	 */
+	private IGraphModelNode getCastedModel() {
+		return (IGraphModelNode)getModel();
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getModelSourceConnections()
+	 */
+	protected List getModelSourceConnections() {
+		if (getCastedModel() == null) return Collections.EMPTY_LIST;
+		return getCastedModel().getSourceConnections();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getModelTargetConnections()
+	 */
+	protected List getModelTargetConnections() {
+		if (getCastedModel() == null) return Collections.EMPTY_LIST;
+		return getCastedModel().getTargetConnections();
+	}
+		
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.NodeEditPart#getSourceConnectionAnchor(org.eclipse.gef.ConnectionEditPart)
+	 */
+	public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection) {
+//		@tag zest(bug(152180-SelfLoops)) : New anchor required so that the loops aren't hidden by the node.
+		if (connection.getSource() == connection.getTarget()) {
+			return getLoopAnchor();
+		}
+		return getDefaultConnectionAnchor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.NodeEditPart#getTargetConnectionAnchor(org.eclipse.gef.ConnectionEditPart)
+	 */
+	public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connection) {
+//		@tag zest(bug(152180-SelfLoops)) : New anchor required so that the loops aren't hidden by the node.
+		if (connection.getSource() == connection.getTarget()) {
+			return getLoopAnchor();
+		}
+		return getDefaultConnectionAnchor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.NodeEditPart#getSourceConnectionAnchor(org.eclipse.gef.Request)
+	 */
+	public ConnectionAnchor getSourceConnectionAnchor(Request request) {
+		return getDefaultConnectionAnchor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.NodeEditPart#getTargetConnectionAnchor(org.eclipse.gef.Request)
+	 */
+	public ConnectionAnchor getTargetConnectionAnchor(Request request) {
+		return getDefaultConnectionAnchor();
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/LoopAnchor.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/LoopAnchor.java
new file mode 100644
index 0000000..6ecb31c
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/LoopAnchor.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.parts;
+
+import org.eclipse.draw2d.ChopboxAnchor;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Point;
+
+public class LoopAnchor extends ChopboxAnchor {
+	public LoopAnchor(IFigure owner) {
+		super(owner);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.ChopboxAnchor#getReferencePoint()
+	 */
+	public Point getReferencePoint() {
+		//modification to getReferencePoint. Returns
+		//a point on the outside of the owners box, rather than the
+		//center. Only usefull for self-loops.
+		if (getOwner() == null)
+			return null;
+		else {
+			Point ref = getOwner().getBounds().getCenter();
+			ref.y = getOwner().getBounds().y;
+			getOwner().translateToAbsolute(ref);
+			return ref;
+		}
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/ProxyConnectionEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/ProxyConnectionEditPart.java
new file mode 100644
index 0000000..a870b20
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/ProxyConnectionEditPart.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.parts;
+
+import org.eclipse.mylar.zest.core.internal.graphmodel.ProxyConnection;
+
+/**
+ * An edit part for creating proxy connections.
+ * @author Del Myers
+ *
+ */
+//@tag bug(153466-NoNestedClientSupply(fix))
+public final class ProxyConnectionEditPart extends GraphConnectionEditPart {
+
+	/**
+	 * 
+	 */
+	public ProxyConnectionEditPart() {
+		super();
+	}
+		
+		
+	public ProxyConnection getProxyModel() {
+		return (ProxyConnection)getModel();
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/tools/OverviewRectangleTool.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/tools/OverviewRectangleTool.java
new file mode 100644
index 0000000..92a4a4f
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/tools/OverviewRectangleTool.java
@@ -0,0 +1,554 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.parts.tools;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Cursors;
+import org.eclipse.draw2d.FigureListener;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.RectangleFigure;
+import org.eclipse.draw2d.Viewport;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.DragTracker;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.RequestConstants;
+import org.eclipse.gef.editparts.ZoomListener;
+import org.eclipse.gef.editparts.ZoomManager;
+import org.eclipse.gef.tools.AbstractTool;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.MouseEvent;
+
+/**
+ * A tool that is used in the graph overview viewer that allows the user to select an area
+ * of the graph to zoom on.
+ * @author Del Myers
+ *
+ */
+public class OverviewRectangleTool extends AbstractTool implements DragTracker, ControlListener, ZoomListener, PropertyChangeListener, FigureListener {
+	private RectangleFigure focusFigure;
+	private int dragState;
+	private Rectangle startBounds;
+	private TargetShape target;
+	private FigureListener focusFigureListener;
+	private Rectangle referenceBounds;
+	private ZoomManager currentManager;
+	
+	private static final int OUTSIDE = 0;
+	private static final int INSIDE = 1<<1;
+	private static final int NORTH = INSIDE | 1<<2;
+	private static final int EAST = INSIDE |1<<3;
+	private static final int SOUTH = INSIDE | 1<<4;
+	private static final int WEST = INSIDE | 1<<5;
+	
+	private static final int NORTHWEST = INSIDE | NORTH | WEST;
+	private static final int NORTHEAST = INSIDE | NORTH | EAST;
+	private static final int SOUTHWEST = INSIDE | SOUTH | WEST;
+	private static final int SOUTHEAST = INSIDE | SOUTH | EAST;
+	
+	private class FocusMoveListener implements FigureListener {
+
+		/* (non-Javadoc)
+		 * @see org.eclipse.draw2d.FigureListener#figureMoved(org.eclipse.draw2d.IFigure)
+		 */
+		public void figureMoved(IFigure source) {
+			//move the target to the center of the figure.
+			setTargetCenter(source.getBounds().getCenter());
+		}
+		
+	}
+	
+	/**
+	 * 
+	 */
+	public OverviewRectangleTool() {
+		setUnloadWhenFinished(false);
+		referenceBounds = new Rectangle();
+		//setEditDomain(new EditDomain());
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.tools.AbstractTool#handleDragStarted()
+	 */
+	protected boolean handleDragStarted() {
+		setState(STATE_DRAG);
+		setDragState(getRelativeCursorLocation(getStartLocation()));
+		Rectangle bounds = getFeedBackFigure().getBounds().getCopy();
+		getFeedBackFigure().translateToAbsolute(bounds);
+		setDragStartBounds(bounds);
+		return true;
+	}
+	
+	/**
+	 * @param bounds
+	 */
+	private void setDragStartBounds(Rectangle bounds) {
+		this.startBounds = bounds.getCopy();
+		
+	}
+
+	private Rectangle getDragStartBounds() {
+		return startBounds;
+	}
+	
+	private void setDragState(int state) {
+		this.dragState = state;
+	}
+	
+	/**
+	 * @return the dragState
+	 */
+	private int getDragState() {
+		return dragState;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.tools.AbstractTool#handleDragInProgress()
+	 */
+	protected boolean handleDragInProgress() {
+		setState(STATE_DRAG_IN_PROGRESS);
+		Dimension delta = getDragMoveDelta();
+		Point start = getStartLocation();
+		RectangleFigure feedBack = getFeedBackFigure();
+		boolean moving = false;
+		int state = getDragState();
+		Rectangle oldBounds = getDragStartBounds();
+		Rectangle newBounds = oldBounds.getCopy();
+		if (isNorth(state)) {
+			newBounds.y = oldBounds.y+delta.height;
+			newBounds.height = oldBounds.height-delta.height;
+		} else if (isSouth(state)) {
+			newBounds.height = oldBounds.height+delta.height;
+		}
+		if (isWest(state)) {
+			newBounds.x = oldBounds.x+delta.width;
+			newBounds.width = oldBounds.width-delta.width;
+		} else if (isEast(state)) {
+			newBounds.width = oldBounds.width+delta.width;
+		}
+		if (!(isWest(state) || isEast(state) || isNorth(state) || isSouth(state))) {
+			if (isInside(state)) {
+				moving = true;
+				newBounds.x = oldBounds.x+delta.width;
+				newBounds.y = oldBounds.y+delta.height;
+			} else {
+				//a new rectangle is drawn.
+				newBounds = new Rectangle(start, delta);
+			}
+		}
+		//adjust the bounds for negative widths and heights
+		if (newBounds.width < 0) {
+			newBounds.x += newBounds.width;
+			newBounds.width = -newBounds.width;
+		}
+		if (newBounds.height < 0) {
+			newBounds.y += newBounds.height;
+			newBounds.height = -newBounds.height;
+		}
+		int minX = getCurrentViewer().getControl().getBounds().x;
+		int minY = getCurrentViewer().getControl().getBounds().y;
+		int maxWidth = getCurrentViewer().getControl().getBounds().width;
+		int maxHeight = getCurrentViewer().getControl().getBounds().height;
+		if (newBounds.x < minX || newBounds.y < minY || 
+			newBounds.x + newBounds.width > minX + maxWidth ||
+			newBounds.y + newBounds.height > minY + maxHeight) {
+			if (moving) {
+				if (newBounds.x < minX) {
+					newBounds.x = minX;
+				} 
+				if (newBounds.y < minY) {
+					newBounds.y = minY;
+				}
+				if (newBounds.x+newBounds.width > minX+maxWidth) {
+					newBounds.x = maxWidth-newBounds.width;;
+				}
+				if (newBounds.y +newBounds.height > minY+maxHeight) {
+					newBounds.y = maxHeight-newBounds.height;
+				}
+			} else {
+				if (newBounds.x < minX) {
+					newBounds.width = newBounds.x+newBounds.width-minX;
+					newBounds.x = minX;
+				}
+				if (newBounds.y < minY) {
+					newBounds.height = newBounds.y+newBounds.height-minY;
+					newBounds.y = minY;
+				}
+				if (newBounds.x+newBounds.width > minX+maxWidth) {
+					newBounds.width = maxWidth-newBounds.x;
+				}
+				if (newBounds.y +newBounds.height > minY+maxHeight) {
+					newBounds.height = maxHeight-newBounds.y;
+				}
+			}
+		}
+		feedBack.translateToRelative(newBounds);
+		feedBack.setBounds(newBounds);
+		return true;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.tools.AbstractTool#handleMove()
+	 */
+	protected boolean handleMove() {
+		Point location = getLocation();
+		switch (getRelativeCursorLocation(location)) {
+		case NORTH:
+		case SOUTH:
+			setCursor(Cursors.SIZENS);
+			break;
+		case EAST:
+		case WEST:
+			setCursor(Cursors.SIZEWE);
+			break;
+		case NORTHWEST:
+		case SOUTHEAST:
+			setCursor(Cursors.SIZENWSE);
+			break;
+		case NORTHEAST:
+		case SOUTHWEST:
+			setCursor(Cursors.SIZENESW);
+			break;
+		case INSIDE:
+			setCursor(Cursors.SIZEALL);
+			break;
+		default:
+			setCursor(getDefaultCursor());
+
+		}
+		return true;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.tools.AbstractTool#handleButtonUp(int)
+	 */
+	protected boolean handleButtonUp(int button) {
+		handleFinished();
+		return true;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.tools.AbstractTool#handleFinished()
+	 */
+	protected void handleFinished() {
+		if (isInState(STATE_DRAG_IN_PROGRESS) || isInState(STATE_DRAG)) {
+			
+		} else {
+			Point location = getLocation();
+			getFeedBackFigure().setBounds(new Rectangle(location.x, location.y, 0,0));
+		}
+		setState(STATE_TERMINAL);
+		resetFlags();
+		zoomTo(getFeedBackFigure().getBounds().getCopy());
+		
+		//super.handleFinished();
+	}
+	
+	/**
+	 * @param copy
+	 */
+	private void zoomTo(Rectangle rect) {
+		referenceBounds = rect.getCopy();
+		GraphicalEditPart part = (GraphicalEditPart)getCurrentViewer().getContents();
+		if (part != null) {
+			part.getFigure().translateFromParent(referenceBounds);
+			if (rect.isEmpty()) {
+				//make sure that it didn't scale to a size greater than 0.
+				referenceBounds.setSize(0,0);
+			}
+			if (this.currentManager != null)
+				this.currentManager.zoomTo(referenceBounds);
+			if (referenceBounds.isEmpty()) {
+				//reset the figure so as to not jar the user.
+				getFeedBackFigure().setBounds(rect);
+			}
+		}
+	}
+	boolean isNorth(int loc) {
+		loc = (isInside(loc)) ? loc ^ INSIDE : loc;
+		return (loc & NORTH) != 0;
+	}
+	
+	boolean isEast(int loc) {
+		loc = (isInside(loc)) ? loc ^ INSIDE : loc;
+		return (loc & EAST)!= 0;
+	}
+	
+	boolean isSouth(int loc) {
+		loc = (isInside(loc)) ? loc ^ INSIDE : loc;
+		return (loc & SOUTH) != 0;
+	}
+	
+	boolean isWest(int loc) {
+		loc = (isInside(loc)) ? loc ^ INSIDE : loc;
+		return (loc & WEST) != 0;
+	}
+	
+	boolean isInside(int loc) {
+		return (loc & INSIDE) != 0;
+	}
+	
+	private int getRelativeCursorLocation(Point location) {
+		RectangleFigure feedBack = getFeedBackFigure();
+		Rectangle bounds = feedBack.getBounds();
+		location = location.getCopy();
+		feedBack.translateToRelative(location);
+		int result = OUTSIDE;
+		if (feedBack.containsPoint(location)) {
+			result |= INSIDE;
+			//check to see the bounds to find out which 
+			//cursor to use
+			if (Math.abs(location.y - bounds.y)<=2) {
+				result |= NORTH;
+			} else if (Math.abs(location.y -(bounds.y+bounds.height-1))<=2) {
+				result |= SOUTH;
+			} 
+			if (Math.abs(location.x - bounds.x)<=2) {
+				result |= WEST;
+			} else if (Math.abs(location.x - (bounds.x+bounds.width-1))<=2) {
+				result |= EAST;
+			}
+		}
+		return result;
+	}
+	
+	private RectangleFigure getFeedBackFigure() {
+		if (focusFigure == null) {
+			focusFigure = new RectangleFigure();
+			focusFigure.setForegroundColor(ColorConstants.red);
+			focusFigure.setFill(false);
+			focusFigure.setLineWidth(2);
+			focusFigureListener = new FocusMoveListener();
+			focusFigure.addFigureListener(focusFigureListener);
+			focusFigure.setBounds(new Rectangle());
+			addFeedback(focusFigure);
+//			referenceBounds = focusFigure.getParent().getBounds().getCopy();
+//			focusFigure.getParent().addFigureListener(this);
+		}
+		return focusFigure;
+	}
+	
+	private TargetShape getTargetFigure() {
+		if (target == null) {
+			target = new TargetShape();
+			target.setForegroundColor(ColorConstants.red);
+			target.setFill(false);
+			target.setBounds(new Rectangle(-10,-10,20,20));
+			target.setLineWidth(2);
+			addFeedback(target);
+		}
+		return target;
+	}
+	
+	private void setTargetCenter(Point center) {
+		Point newCenter = center.getCopy();
+		newCenter.translate(-getTargetFigure().getSize().width/2, -getTargetFigure().getSize().height/2);
+		getTargetFigure().setLocation(newCenter);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.tools.AbstractTool#deactivate()
+	 */
+	public void deactivate() {
+		if (focusFigure != null) {
+			focusFigure.removeFigureListener(focusFigureListener);
+			removeFeedback(focusFigure);
+			focusFigure = null;
+		}
+		if (target != null) {
+			removeFeedback(target);
+			target = null;
+		}
+		if (getCurrentViewer() != null) {
+			getCurrentViewer().getControl().removeControlListener(this);
+			if (getCurrentViewer().getContents() instanceof GraphicalEditPart) {
+				((GraphicalEditPart)getCurrentViewer().getContents()).getFigure().removeFigureListener(this);
+			}
+		}
+		if (this.currentManager != null) {
+			this.currentManager.removeZoomListener(this);
+			this.currentManager.getViewport().getHorizontalRangeModel().removePropertyChangeListener(this);
+			this.currentManager.getViewport().getVerticalRangeModel().removePropertyChangeListener(this);
+		}
+		super.deactivate();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.tools.AbstractTool#activate()
+	 */
+	public void activate() {
+	
+		super.activate();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.tools.AbstractTool#getCommandName()
+	 */
+	protected String getCommandName() {
+		return RequestConstants.REQ_SELECTION;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.tools.AbstractTool#setViewer(org.eclipse.gef.EditPartViewer)
+	 */
+	public void setViewer(EditPartViewer viewer) {
+		if (getCurrentViewer() != null) {
+			getCurrentViewer().getControl().removeControlListener(this);
+			GraphicalEditPart part = (GraphicalEditPart) getCurrentViewer().getContents();
+			if (part != null) {
+				IFigure referenceFigure = part.getContentPane();
+				referenceFigure.removeFigureListener(this);
+			}
+		}
+		super.setViewer(viewer);
+				
+		if (getCurrentViewer() != null) {
+			getCurrentViewer().getControl().addControlListener(this);
+			GraphicalEditPart part = (GraphicalEditPart) getCurrentViewer().getContents();
+			if (part != null) {
+				IFigure referenceFigure = part.getContentPane();
+				referenceFigure.addFigureListener(this);
+			}
+		}
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt.events.ControlEvent)
+	 */
+	public void controlMoved(ControlEvent e) {}
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.events.ControlListener#controlResized(org.eclipse.swt.events.ControlEvent)
+	 */
+	public void controlResized(ControlEvent e) {}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.tools.AbstractTool#viewerExited(org.eclipse.swt.events.MouseEvent, org.eclipse.gef.EditPartViewer)
+	 */
+	public void viewerExited(MouseEvent me, EditPartViewer viewer) {
+//		//don't want to reset the viewer to null
+//		if (viewer == getCurrentViewer()) {
+//			handleViewerExited();
+//			getCurrentInput().setInput(me);
+//		}
+		super.viewerExited(me, viewer);
+	}
+	/**
+	 * @param zoomManager
+	 */
+	public void setZoomManager(ZoomManager zoomManager) {
+		if (this.currentManager != null) {
+			this.currentManager.removeZoomListener(this);
+			this.currentManager.getViewport().getHorizontalRangeModel().removePropertyChangeListener(this);
+			this.currentManager.getViewport().getVerticalRangeModel().removePropertyChangeListener(this);
+		}
+		this.currentManager = zoomManager;
+		if (this.currentManager != null) {
+			this.currentManager.addZoomListener(this);
+			this.currentManager.getViewport().getHorizontalRangeModel().addPropertyChangeListener(this);
+			this.currentManager.getViewport().getVerticalRangeModel().addPropertyChangeListener(this);
+			//make sure that everthing is up-to-date.
+			IFigure referenceFigure = getReferenceFigure();
+			if (referenceFigure != null)
+				getCurrentViewer().flush();
+		}
+		updateViewPort();
+	}
+	
+	private IFigure getReferenceFigure() {
+		GraphicalEditPart part = getReferenceEditPart();
+		if (part != null)
+			return part.getFigure();
+		return null;
+	}
+	
+	
+	/**
+	 * @return
+	 */
+	private GraphicalEditPart getReferenceEditPart() {
+		if (getCurrentViewer() == null) return null;
+		if (getCurrentViewer().getContents() instanceof GraphicalEditPart) {
+			return (GraphicalEditPart) getCurrentViewer().getContents();
+		}
+		return null;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.ZoomListener#zoomChanged(double)
+	 */
+	public void zoomChanged(double zoom) {
+//		Viewport viewport = this.currentManager.getViewport();
+//		if (Math.abs(1-zoom) < .1) {
+//			//set the bounds of the rectangle to zeros
+//			getFeedBackFigure().setBounds(new Rectangle());
+//		}
+//		//adjust the feedback according to the zoom.
+//		int x = viewport.getHorizontalRangeModel().getValue();
+//		int width = viewport.getHorizontalRangeModel().getExtent();
+//		int y = viewport.getVerticalRangeModel().getValue();
+//		int height = viewport.getVerticalRangeModel().getExtent();
+//		Rectangle newBounds = new Rectangle(x,y,width,height);
+//		//translate it.
+		
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+	 */
+	public void propertyChange(PropertyChangeEvent evt) {
+		updateViewPort();		
+	}
+	/**
+	 * 
+	 */
+	private void updateViewPort() {
+		if (this.currentManager == null) return;
+		if (getCurrentViewer() == null) return;
+		Viewport viewport = this.currentManager.getViewport();
+		double zoom = this.currentManager.getZoom();
+//		adjust the feedback according to the zoom.
+		int x = viewport.getHorizontalRangeModel().getValue();
+		int width = viewport.getHorizontalRangeModel().getExtent();
+		int y = viewport.getVerticalRangeModel().getValue();
+		int height = viewport.getVerticalRangeModel().getExtent();
+		if (Math.abs(1-zoom) < .1) {
+			//set the bounds of the rectangle to zeros
+			x+= width/2;
+			y+= height/2;
+			width = 0;
+			height = 0;
+		}
+		Rectangle newBounds = new Rectangle(x,y,width,height);
+		GraphicalEditPart part = (GraphicalEditPart) getCurrentViewer().getContents();
+		if (part != null) {
+			IFigure referenceFigure = part.getContentPane();
+			newBounds.scale(1/this.currentManager.getZoom());
+			referenceFigure.translateToParent(newBounds);
+			//adjust for the insets on the figure
+			//newBounds.crop(getFeedBackFigure().getInsets());
+			newBounds.shrink(1,1);//getFeedBackFigure().getLineWidth(), getFeedBackFigure().getLineWidth());
+			getFeedBackFigure().setBounds(newBounds);
+		}
+		
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.FigureListener#figureMoved(org.eclipse.draw2d.IFigure)
+	 */
+	public void figureMoved(IFigure source) {
+		updateViewPort();
+		
+	}
+	
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/tools/TargetShape.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/tools/TargetShape.java
new file mode 100644
index 0000000..3924c37
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/parts/tools/TargetShape.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.parts.tools;
+
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Shape;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+/**
+ * TODO comment
+ * @author Del Myers
+ *
+ */
+public class TargetShape extends Shape {
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Shape#fillShape(org.eclipse.draw2d.Graphics)
+	 */
+	protected void fillShape(Graphics graphics) {
+		//does nothing.
+
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Shape#outlineShape(org.eclipse.draw2d.Graphics)
+	 */
+	protected void outlineShape(Graphics graphics) {
+		Rectangle bounds = getClientArea().getCopy();
+		//reduce the bounds by one pixel so that it can be properly
+		//drawn within the clipping region.
+		//graphics.setXORMode(true);
+		bounds.width -= 1;
+		bounds.height -= 1;
+		Point center = bounds.getCenter();
+		Point bottom = new Point(bounds.x+bounds.width, bounds.height+bounds.y);
+		Point top = new Point(bounds.x, bounds.y);
+		//draw the crosshairs
+		graphics.drawLine(center.x, top.y, center.x, center.y-2);
+		graphics.drawLine(center.x+2, center.y, bottom.x, center.y);
+		graphics.drawLine(center.x, center.y+2, center.x, bottom.y);
+		graphics.drawLine(top.x, center.y, center.x-2, center.y);
+		//draw the circle target.
+		bounds.shrink(bounds.width/4, bounds.height/4);
+		bounds.width -=1;
+		bounds.height -=1;
+//		bounds.x+=1;
+//		bounds.y+=1;
+		graphics.drawOval(bounds);
+		
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/policies/ColorSelectionEditPolicy.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/policies/ColorSelectionEditPolicy.java
new file mode 100644
index 0000000..cfd3d6a
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/policies/ColorSelectionEditPolicy.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.policies;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PrecisionRectangle;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.editpolicies.NonResizableEditPolicy;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphNodeEditPart;
+
+/**
+ * The ColorSelectionEditPolicy class hides the selection handles at the corners
+ * and instead uses a different color for the object to indicate selection.
+ * 
+ * @author Chris Callendar
+ */
+public class ColorSelectionEditPolicy extends NonResizableEditPolicy {
+
+	private GraphNodeEditPart editPart;
+
+	/**
+	 * ColorSelectionEditPolicy constructor.
+	 */
+	public ColorSelectionEditPolicy(GraphNodeEditPart editPart) {
+		this.editPart = editPart;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.gef.editpolicies.NonResizableEditPolicy#createSelectionHandles()
+	 */
+	protected List createSelectionHandles() {
+		return Collections.EMPTY_LIST;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.gef.editpolicies.SelectionEditPolicy#hideSelection()
+	 */
+	protected void hideSelection() {
+		//@tag bug(unreported(fix)) : let the model take care of highlighting, otherwise it gets unsynchronized with the view.
+		((IGraphModelNode)editPart.getModel()).unhighlight();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.gef.editpolicies.SelectionEditPolicy#showSelection()
+	 */
+	protected void showSelection() {
+//		@tag bug(unreported(fix)) : let the model take care of highlighting, otherwise it gets unsynchronized with the view.
+		((IGraphModelNode)editPart.getModel()).highlight();
+
+		// move the current editpart's figure to last in the list to put it on
+		// top of the other nodes
+		IFigure fig = editPart.getFigure();
+		fig.getParent().getChildren().remove(fig);
+		fig.getParent().getChildren().add(fig);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.NonResizableEditPolicy#showChangeBoundsFeedback(org.eclipse.gef.requests.ChangeBoundsRequest)
+	 */
+	protected void showChangeBoundsFeedback(ChangeBoundsRequest request) {
+		IFigure feedback = getDragSourceFeedbackFigure();
+		IGraphModelNode node = (IGraphModelNode)editPart.getModel();
+		PrecisionRectangle rect = new PrecisionRectangle(new Rectangle(node.getLocation(), node.getSize()));
+		getCurrentLocation(request, rect, feedback);
+		feedback.getParent().setConstraint(feedback, rect);
+	}
+
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.NonResizableEditPolicy#getDragSourceFeedbackFigure()
+	 */
+	protected IFigure getDragSourceFeedbackFigure() {
+		return editPart.getFigure();
+	}
+	
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.gef.editpolicies.NonResizableEditPolicy#eraseChangeBoundsFeedback(org.eclipse.gef.requests.ChangeBoundsRequest)
+	 */
+	protected void eraseChangeBoundsFeedback(ChangeBoundsRequest request) {
+		IFigure feedback = getDragSourceFeedbackFigure();
+		IGraphModelNode node = (IGraphModelNode)editPart.getModel();
+		PrecisionRectangle rect = new PrecisionRectangle(new Rectangle(node.getLocation(), node.getSize()));
+		getCurrentLocation(request, rect, feedback);
+		((IGraphModelNode) editPart.getModel()).setHasPreferredLocation(false);
+		((IGraphModelNode) editPart.getModel()).setPreferredLocation(rect.x, rect.y);
+	}
+	
+	
+	/**
+	 * Gets the current location based on the original location of the node, 
+	 * and the current request.
+	 * @param request The current request
+	 * @param startingBounds The starting location of the node
+	 * @param feedback The feedback figure being moved
+	 * @return The current position of the node
+	 */
+	private Point getCurrentLocation(ChangeBoundsRequest request, PrecisionRectangle startingBounds, IFigure feedback) {
+		getHostFigure().translateToAbsolute(startingBounds);
+		startingBounds.translate(request.getMoveDelta());
+		startingBounds.resize(request.getSizeDelta());
+		feedback.translateToRelative(startingBounds);
+		return new Point(startingBounds.x, startingBounds.y);
+	}
+
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/policies/GraphXYLayoutEditPolicy.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/policies/GraphXYLayoutEditPolicy.java
new file mode 100644
index 0000000..f7f9895
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/policies/GraphXYLayoutEditPolicy.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.policies;
+
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.editpolicies.XYLayoutEditPolicy;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.gef.requests.CreateRequest;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphNodeEditPart;
+import org.eclipse.mylar.zest.core.internal.viewers.commands.NoResizeNodeConstraintCommand;
+
+
+
+/**
+ * Extends XYLayoutEditPolicy to use a child color selection policy (no resizing or handles), and to get create and delete 
+ * commands.
+ * 
+ * @author Chris Callendar
+ */
+public class GraphXYLayoutEditPolicy extends XYLayoutEditPolicy {
+	
+	public GraphXYLayoutEditPolicy() {
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#createAddCommand(org.eclipse.gef.EditPart, java.lang.Object)
+	 */
+	protected Command createAddCommand(EditPart child, Object constraint) {
+		return null;
+	}
+		
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#createChildEditPolicy(org.eclipse.gef.EditPart)
+	 */
+	protected EditPolicy createChildEditPolicy(EditPart child) {
+		
+		if (child instanceof GraphNodeEditPart) {
+			return new ColorSelectionEditPolicy((GraphNodeEditPart)child);
+		}
+		
+		return super.createChildEditPolicy(child);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#createChangeConstraintCommand(org.eclipse.gef.requests.ChangeBoundsRequest, org.eclipse.gef.EditPart, java.lang.Object)
+	 */
+	protected Command createChangeConstraintCommand(ChangeBoundsRequest request, EditPart child, Object constraint) {
+		if ((child instanceof GraphNodeEditPart) && (constraint instanceof Rectangle)) {
+			// return a command that allows nodes to move
+			GraphNodeEditPart editPart = (GraphNodeEditPart) child;
+			NoResizeNodeConstraintCommand cmd = new NoResizeNodeConstraintCommand((IGraphModelNode)editPart.getModel(), request, (Rectangle)constraint);
+			return cmd;
+		}
+		return super.createChangeConstraintCommand(request, child, constraint);
+	}
+	
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#createChangeConstraintCommand(org.eclipse.gef.EditPart, java.lang.Object)
+	 */
+	protected Command createChangeConstraintCommand(EditPart child, Object constraint) {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.LayoutEditPolicy#getCreateCommand(org.eclipse.gef.requests.CreateRequest)
+	 */
+	protected Command getCreateCommand(CreateRequest request) {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.LayoutEditPolicy#getDeleteDependantCommand(org.eclipse.gef.Request)
+	 */
+	protected Command getDeleteDependantCommand(Request request) {
+		return null;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/policies/HighlightConnectionEndpointEditPolicy.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/policies/HighlightConnectionEndpointEditPolicy.java
new file mode 100644
index 0000000..be0582d
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/graphviewer/policies/HighlightConnectionEndpointEditPolicy.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.graphviewer.policies;
+
+import org.eclipse.gef.editpolicies.ConnectionEndpointEditPolicy;
+
+/**
+ * This uses both end point to highlight the edge and makes the edge thicker
+ * 
+ * @author Ian Bull
+ *
+ */
+public class HighlightConnectionEndpointEditPolicy extends ConnectionEndpointEditPolicy {
+	
+	protected void showSelection() {
+		super.showSelection();
+	}
+	
+	protected void hideSelection() {
+		super.hideSelection();
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/NestedGraphViewerImpl.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/NestedGraphViewerImpl.java
new file mode 100644
index 0000000..c9d09f4
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/NestedGraphViewerImpl.java
@@ -0,0 +1,452 @@
+/*******************************************************************************
+ * Copyright 2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.draw2d.Animation;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+import org.eclipse.gef.editparts.LayerManager;
+import org.eclipse.mylar.zest.core.IZestColorConstants;
+import org.eclipse.mylar.zest.core.ZestPlugin;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.core.internal.gefx.NestedNonThreadedGraphicalViewer;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NodeChildrenComparator;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts.NestedGraphEditPartFactory;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts.NestedGraphNodeEditPart;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts.NestedGraphRootEditPart;
+import org.eclipse.mylar.zest.layouts.InvalidLayoutConfiguration;
+import org.eclipse.mylar.zest.layouts.LayoutAlgorithm;
+import org.eclipse.mylar.zest.layouts.LayoutEntity;
+import org.eclipse.mylar.zest.layouts.LayoutRelationship;
+import org.eclipse.mylar.zest.layouts.LayoutStyles;
+import org.eclipse.mylar.zest.layouts.algorithms.GridLayoutAlgorithm;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Widget;
+
+
+/**
+ * The GEF GraphicalViewerImpl extension for nested graphs.
+ * 
+ * @author Chris Callendar 
+ */
+public class NestedGraphViewerImpl extends NestedNonThreadedGraphicalViewer  {
+	
+	private NestedGraphModel model = null;
+	private NestedGraphEditPartFactory editPartFactory = null;
+	private LayoutAlgorithm layoutAlgorithm;
+	private HashMap nodeColorMap = new HashMap();
+	Composite parent = null;
+	
+	// styles
+	private int style = ZestStyles.NONE;
+	private boolean allowOverlap = false;
+	private boolean enforceBounds = false;
+	//private boolean directedGraph = false;
+	
+	/**
+	 * Initializes the viewer with the given styles (NO_SCROLLBARS, ZOOM_REAL, ZOOM_FAKE, ZOOM_EXPAND).  
+	 * @see ZestStyles
+	 * @param parent
+	 * @param style the styles for the viewer
+	 * @see ZestStyles#NO_OVERLAPPING_NODES
+	 * @see ZestStyles#NODES_HIGHLIGHT_ADJACENT
+	 * @see ZestStyles#ENFORCE_BOUNDS
+	 * @see ZestStyles#ZOOM_EXPAND
+	 * @see ZestStyles#ZOOM_FAKE
+	 * @see ZestStyles#ZOOM_REAL
+	 * @see ZestStyles#DIRECTED_GRAPH
+	 */
+	public NestedGraphViewerImpl(Composite parent, int style) {
+		super(parent);
+		setStyle(style);
+		this.parent = parent;
+	}
+	
+	/**
+	 * Sets the style on the NestedGraphViewer
+	 * @param style the style
+	 * @see ZestStyles#NO_OVERLAPPING_NODES
+	 * @see ZestStyles#NODES_HIGHLIGHT_ADJACENT
+	 * @see ZestStyles#ENFORCE_BOUNDS
+	 * @see ZestStyles#ZOOM_EXPAND
+	 * @see ZestStyles#ZOOM_FAKE
+	 * @see ZestStyles#ZOOM_REAL
+	 * @see ZestStyles#DIRECTED_GRAPH
+	 */
+	public void setStyle(int style) {
+		this.style = style;
+		this.allowOverlap = !ZestStyles.checkStyle(style, ZestStyles.NO_OVERLAPPING_NODES);
+		this.enforceBounds = ZestStyles.checkStyle(style, ZestStyles.ENFORCE_BOUNDS);
+		//this.directedGraph = ZestStyles.checkStyle(style, ZestStyles.DIRECTED_GRAPH);
+	}
+	
+	/**
+	 * Returns the style for this viewer.
+	 * @return int the style for the viewer
+	 */
+	public int getStyle() {
+		return style;
+	}
+    
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.ui.parts.GraphicalViewerImpl#createDefaultRoot()
+	 */
+	protected void createDefaultRoot() {
+		setRootEditPart(new NestedGraphRootEditPart());
+	}
+	
+	/* (non-Javadoc)
+	 * @see ca.uvic.cs.zest.internal.gefx.ThreadedGraphicalViewer#configureGraphicalViewer()
+	 */
+	protected void configureGraphicalViewer() {
+		NestedGraphRootEditPart root = (NestedGraphRootEditPart) getRootEditPart();
+		root.clear();
+		if (editPartFactory == null) {
+			editPartFactory = new NestedGraphEditPartFactory(root, allowOverlap, enforceBounds);
+		}
+		//this.setRootEditPart(root);
+		this.setEditPartFactory(editPartFactory);
+	}
+
+	/**
+	 * Sets the model.
+	 */
+	public void setContents(NestedGraphModel model) {
+		if ((this.model != null) && (this.model != model)) {
+			// release the old model
+			this.model.dispose();
+		}
+		this.model = model;
+		fireModelUpdate();
+	}
+	
+	/**
+	 * Updates the graph based on the model.  This method
+	 * will be called when the model changes.
+	 * Some form of zooming might be performed.
+	 */
+	public void fireModelUpdate() {
+		NestedGraphModelNode previousNode = model.getPreviousRootNode();
+		NestedGraphModelNode nodeToMoveTo = model.getCurrentNode();
+		NestedGraphModelNode nodeToSelect = nodeToMoveTo;	// node to select in the TreeViewer
+		if (getContents() == null) {
+			doSetContents(model);
+			doLayout(nodeToMoveTo,500, 500);
+			return;
+		}
+		
+		//@tag zest(bug(152393-TopSelection(fix))) : set-up the colors for selected nodes.
+		//@tag zest(bug(151327-Styles(todo))) : this set-up should be done by the GraphItemStyler, not hard-coded.
+		if (previousNode != null) {
+			Color[] colors = (Color[]) nodeColorMap.get(previousNode);
+			if (colors != null) {
+				previousNode.setBackgroundColor(colors[0]);
+				previousNode.setForegroundColor(colors[1]);
+			}
+			nodeColorMap.remove(previousNode);
+		}
+		if (nodeToMoveTo != null) {
+			//set the color to dark-blue
+	
+			nodeColorMap.put(nodeToMoveTo, new Color[] {
+				nodeToMoveTo.getBackgroundColor(),
+				nodeToMoveTo.getForegroundColor()
+			});
+			nodeToMoveTo.setBackgroundColor(ZestPlugin.getDefault().getColor(IZestColorConstants.BLUE));
+			nodeToMoveTo.setForegroundColor(ZestPlugin.getDefault().getColor(IZestColorConstants.LIGHT_GRAY));
+		}
+
+
+		if (this.getRootEditPart() instanceof NestedGraphRootEditPart) {
+			NestedGraphRootEditPart rootEditPart = (NestedGraphRootEditPart)getRootEditPart();
+			if (rootEditPart.getNestedEditPart() == null) return;
+			if ( previousNode == null ) {
+				NestedGraphNodeEditPart zoomPart = (NestedGraphNodeEditPart) getEditPartRegistry().get(nodeToMoveTo);
+				rootEditPart.getNestedEditPart().zoomInOnNode( zoomPart);
+				doSetContents(model);
+			}
+			else if ( nodeToMoveTo.getRelationshipBetweenNodes( previousNode ) == NestedGraphModelNode.DESCENDANT ) {
+				NestedGraphNodeEditPart zoomPart = (NestedGraphNodeEditPart) getEditPartRegistry().get(nodeToMoveTo);
+				rootEditPart.getNestedEditPart().zoomInOnNode( zoomPart);
+				
+				doSetContents(model);
+				
+			}
+			else if ( nodeToMoveTo.getRelationshipBetweenNodes( previousNode ) == NestedGraphModelNode.ANCESTOR) {
+				checkScaling(previousNode);
+				doSetContents(model);
+				getLightweightSystem().getUpdateManager().performValidation();
+				nodeToSelect = previousNode;  // select the previous node
+				flush();
+				
+				if (getEditPartRegistry().containsKey(nodeToSelect)) {
+					//nodeToSelect.setSelected(true);
+					//setSelection(new StructuredSelection(getEditPartRegistry().get(nodeToSelect)));
+					//this.setFocus(this.getRootEditPart());
+				}
+				
+				// now do the zoom (sizes and locations should be set)
+				rootEditPart = (NestedGraphRootEditPart)getRootEditPart();
+				NestedGraphNodeEditPart zoomPart = (NestedGraphNodeEditPart) getEditPartRegistry().get(previousNode);
+				rootEditPart.getNestedEditPart().zoomOutOnNode( zoomPart);//(NestedGraphNodeEditPart)previousNode.getEditPart());
+				//doSetContents(model);
+			}
+			else {
+				NestedGraphModelNode commonParent = previousNode.findCommonParent(nodeToMoveTo);
+				/*LinkedList parentStack = new LinkedList();
+				NestedGraphModelNode node = previousNode.getCastedParent();
+				while (node != commonParent) {
+					parentStack.addLast(node);
+					node = node.getCastedParent();
+				}
+				parentStack.addLast(node);
+				while (parentStack.size() > 0) {*/
+					NestedGraphModelNode node = commonParent;//(NestedGraphModelNode) parentStack.removeFirst();
+					model.setCurrentNode(node);
+					doSetContents(model);
+					getLightweightSystem().getUpdateManager().performValidation();
+					flush();
+					
+					if (getEditPartRegistry().containsKey(nodeToSelect)) {
+						//nodeToSelect.setSelected(true);
+						//setSelection(new StructuredSelection(getEditPartRegistry().get(nodeToSelect)));
+						//this.setFocus(this.getRootEditPart());
+					}
+					
+					// now do the zoom (sizes and locations should be set)
+					rootEditPart = (NestedGraphRootEditPart)getRootEditPart();
+					NestedGraphNodeEditPart zoomPart = (NestedGraphNodeEditPart) getEditPartRegistry().get(previousNode);
+					rootEditPart.getNestedEditPart().zoomOutOnNode( zoomPart);
+				//}
+				model.setCurrentNode(nodeToMoveTo);
+				zoomPart = (NestedGraphNodeEditPart) getEditPartRegistry().get(nodeToMoveTo);
+				rootEditPart.getNestedEditPart().zoomInOnNode( zoomPart);
+				doSetContents(model);
+			}
+		}
+		else {
+			doSetContents(model);
+		}
+//		 layout the children in a grid layout
+		// only happens the first time a node is the current node
+		doLayout(nodeToMoveTo,500, 500);
+			
+	}
+
+
+	
+	/**
+	 * @param model2
+	 */
+	private void doSetContents(NestedGraphModel model) {
+		//@tag bug(153466-NoNestedClientSupply(fix)) : clear proxies before resetting the model.
+		model.clearProxies();
+		super.setContents(model);
+		//filter out connections that aren't within the current node, or to proxies.
+		if (((NestedGraphRootEditPart)getRootEditPart()).getNestedEditPart() != null)
+			((NestedGraphRootEditPart)getRootEditPart()).getNestedEditPart().filterConnections(model.getCurrentNode(), true);
+		
+	}
+
+	/**
+	 * Applies a grid layout to the children of the given node ONLY if it hasn't 
+	 * been already been done.  To force the layout to run again you must call 
+	 * nodeToLayout.setData("GridLayout", null);
+	 * @see Widget#setData(java.lang.String, java.lang.Object)
+	 * @param nodeToLayout The node whose children are going to be displayed in a grid
+	 * @param width		the total available width
+	 * @param height	the total available height
+	 */
+	public void doLayout(NestedGraphModelNode nodeToLayout, double width, double height) {
+		// apply the current layout on any node that hasn't aleady been layed out
+		
+		// Check that we have a width, height, and the total number of nodes to layout is not 0.
+		// Also make sure that the layout is not currently running
+		if ((width > 0) && 
+			(height > 0) && 
+			(nodeToLayout.getChildren().size() > 0 ) &&
+			!("true".equals(nodeToLayout.getData("LayoutCompleted")))) {
+			
+			List children = nodeToLayout.getChildren();
+			LayoutEntity[] entities = new LayoutEntity[children.size()];
+			entities = (LayoutEntity[])children.toArray(entities);
+
+			// put the nodes who have no children last
+			Arrays.sort(entities, new NodeChildrenComparator());
+			
+			if (layoutAlgorithm == null) {
+				layoutAlgorithm = new GridLayoutAlgorithm(LayoutStyles.NONE);
+				((GridLayoutAlgorithm)layoutAlgorithm).setRowPadding(20);
+			}
+			layoutAlgorithm.setEntityAspectRatio(width / height);
+			try {
+				//perform an update so that the state of all the figures are saved
+				getLightweightSystem().getUpdateManager().performUpdate();
+				Animation.markBegin();
+				layoutAlgorithm.applyLayout(entities, new LayoutRelationship[0], 0, 0, width - 20, height - 40, false, false);
+				Animation.run(1000);
+				
+				//animator.animateNodes(animateableNodes);
+				// set this attribute to signal the a grid layout has occured
+				// this way the grid layout is only done once.
+				nodeToLayout.setData("LayoutCompleted", "true");
+				
+				// now resize any node that has no children
+				for (Iterator iter = children.iterator(); iter.hasNext(); ) {
+					NestedGraphModelNode node = (NestedGraphModelNode)iter.next();
+					if (!node.hasChildren()) {
+						node.setSizeInLayout(node.getWidthInLayout(), node.getMinimizedSize().height);
+					}				
+				}
+				
+			} catch (InvalidLayoutConfiguration ilc) {
+				throw new RuntimeException(ilc.getMessage());
+			}
+		}
+	}
+	
+	/**
+	 * Checks the size of the given node with the size of its children.
+	 * If the children (unscaled) are bigger than the node then the node is scaled
+	 * to make the children all visible.
+	 * @param rootNode
+	 */
+	public void checkScaling(NestedGraphModelNode rootNode) {
+		if (rootNode != null) {
+			double width = rootNode.getWidthInLayout();
+			double height = rootNode.getHeightInLayout() - rootNode.calculateMinimumLabelSize().height;
+			
+			// the minimum size without scaling
+			Dimension minSize = rootNode.calculateMinimumSize();
+			double minWidth = minSize.width;
+			double minHeight = minSize.height;
+			
+			
+			double scale = 1;
+			double xscale = 1.0;
+			double yscale = 1.0;
+
+			xscale = width / minWidth;
+			yscale = height / minHeight;
+			scale = Math.min(xscale, yscale);
+
+			scale = (double) ((int) (100 * scale)) / 100D; // chop to 2 decimal
+															// places
+
+			if (rootNode.getCastedParent() != null) {
+				xscale *= rootNode.getCastedParent().getWidthScale();
+				yscale *= rootNode.getCastedParent().getHeightScale();
+			}
+
+			rootNode.setScale(xscale, yscale);
+
+		}
+	}
+	
+	
+
+	
+	
+	
+	
+	
+	public void setCurrentNode(NestedGraphModelNode modelNode) {
+		NestedGraphModelNode lastNode = model.getCurrentNode(); 
+		if ((modelNode != null) && !modelNode.equals(lastNode)) {
+			model.setCurrentNode(modelNode);
+			fireModelUpdate();	
+		}
+	}
+	
+	public void goBack() {
+		model.goBack();
+		fireModelUpdate();
+	}
+	
+	public void goForward() {
+		model.goForward();
+		fireModelUpdate();
+	}
+	
+	public void goUp() {
+		model.goUp();
+		fireModelUpdate();
+	}
+
+	
+	/**
+	 * Gets an array of the selected model elements (Widget objects).
+	 * @return Widget[]
+	 */
+	public Widget[] getSelectedModelElements() {
+		Widget[] items = new Widget[ getSelectedEditParts().size() ];
+		int i = 0;
+		for (Iterator iterator = getSelectedEditParts().iterator(); iterator.hasNext(); ) {
+			AbstractGraphicalEditPart editPart =(AbstractGraphicalEditPart) iterator.next(); 
+			Object modelElement = (Object)editPart.getModel();
+			if ( modelElement.equals(LayerManager.ID)) {
+				items[i++] = getControl();
+			} else {
+				items[i++] = (Widget)modelElement;
+			}
+		}
+		return items;
+	}
+
+    /**
+     * Resizes the NestedFreeformLayer figure.
+     * @param widthHint
+     * @param heightHint
+     */
+//    public void resize(int widthHint, int heightHint) {
+//		if (getEditPartRegistry().containsKey(model)) {
+//			//System.out.println(getRootEditPart());
+//			((NestedGraphRootEditPart)getRootEditPart()).resize(widthHint, heightHint);
+//			//NestedGraphEditPart editPart = (NestedGraphEditPart)getEditPartRegistry().get(model);
+//			//NestedFreeformLayer layer = (NestedFreeformLayer)editPart.getFigure();
+//			
+//			/*
+//			Rectangle mainArea = layer.resize(widthHint, heightHint);
+//			getFigureCanvas().layout(true, true);
+//			Rectangle oldArea = model.getMainArea();
+//			
+//			model.setMainArea(mainArea);
+//			if (oldArea.isEmpty()) {
+//				doLayout(model.getCurrentNode(), mainArea.width, mainArea.height);
+//			}
+//			*/
+//			
+//			
+//		}
+//    }
+
+	/**
+	 * Sets the layout algorithm to use and re-runs the layout.
+	 * @param algorithm
+	 */
+	public void setLayoutAlgorithm(LayoutAlgorithm algorithm) {
+		this.layoutAlgorithm = algorithm;
+		NestedGraphModelNode node = model.getCurrentNode();
+		if (node != null) {
+			node.setData("LayoutCompleted", "false");
+			doLayout(node, ((NestedGraphRootEditPart)getRootEditPart()).getNestedEditPart().getMainArea().width, model.getMainArea().height);
+		}
+	}
+        
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/FigureGridLayout.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/FigureGridLayout.java
new file mode 100644
index 0000000..f35b733
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/FigureGridLayout.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+import org.eclipse.draw2d.FreeformLayout;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+/**
+ * A layout used to place figures in an automatic grid.
+ * @author Del Myers
+ *
+ */
+
+//@tag bug(150585-TopArcs(fix)) : This layout is used in the client/supplier panes that are related to the top-level node in the nested graph.
+public class FigureGridLayout extends FreeformLayout {
+	public static final Comparator SimpleComparator = new SimpleStringComparator();
+	
+	
+	private static final class SimpleStringComparator implements Comparator {
+		public int compare(Object arg0, Object arg1) {
+			return arg0.toString().compareTo(arg1.toString());
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.XYLayout#layout(org.eclipse.draw2d.IFigure)
+	 */
+	public void layout(IFigure parent) {
+		List children = parent.getChildren();
+		IFigure[] figures = (IFigure[])children.toArray(new IFigure[children.size()]);
+		Arrays.sort(figures, SimpleComparator);
+		Rectangle[] boundss = layoutInBounds(parent.getBounds(), figures);
+		for (int i = 0; i < boundss.length; i++) {
+			figures[i].setBounds(boundss[i]);
+		}
+	}
+	/**
+	 * Convenience method for laying out the given figures within the given bounds.
+	 * An optional comparator can be provided in order to guarantee the order that
+	 * the figures will be layed out.
+	 * @param bounds
+	 * @param figures
+	 * @param sorter
+	 */
+	public static Rectangle[] layoutInBounds(Rectangle bounds, IFigure[] figures) {
+		if (figures.length <= 0) return new Rectangle[0];
+		ArrayList boundss = new ArrayList();
+		int cols = Math.max (1, (int)Math.ceil(Math.sqrt(figures.length)));
+		int width = bounds.width/cols;
+		int height = bounds.height/cols;
+		int pad = 4;
+		int index = 0;
+		for (int i = 0; i < figures.length; i++) {
+			int x = (index % cols)*width;
+			int y = (index/cols)*height;
+			Rectangle figureBounds = new Rectangle(bounds.x+x+pad, bounds.y+y+pad, width-2*pad, height-2*pad);
+			boundss.add(figureBounds);
+			index++;
+		}
+		return (Rectangle[])boundss.toArray(new Rectangle[boundss.size()]);
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphConnectionEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphConnectionEditPart.java
new file mode 100644
index 0000000..4cc6853
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphConnectionEditPart.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts;
+
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Shape;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphConnectionEditPart;
+
+
+/**
+ * @author Chris Callendar
+ * @deprecated by Del Myers. There is no need for NestedGraphConnectionEditParts. Use general GraphConnectionEditParts instead.
+ */
+public class NestedGraphConnectionEditPart extends GraphConnectionEditPart {
+
+	/**
+	 * 
+	 */
+	public NestedGraphConnectionEditPart() {
+		super();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.springgraphviewer.parts.GraphConnectionEditPart#createFigure()
+	 */
+	protected IFigure createFigure() {
+		
+		Connection connection = (Connection)super.createFigure();
+		// Now only directed edges have arrow endpoints - see ZestStyles.DIRECTED_GRAPH
+		//connection.setTargetDecoration(new PolygonDecoration()); // arrow at target endpoint
+		connection.setForegroundColor(getCastedModel().getLineColor());
+		if (connection instanceof Shape) {
+			((Shape)connection).setLineWidth(getCastedModel().getLineWidth());
+			((Shape)connection).setLineStyle(getCastedModel().getLineStyle());
+		}
+		return connection;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphEditPart.java
new file mode 100644
index 0000000..9332132
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphEditPart.java
@@ -0,0 +1,672 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.draw2d.AbstractLayout;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Layer;
+import org.eclipse.draw2d.XYLayout;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.GraphicalEditPart;
+import org.eclipse.gef.LayerConstants;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphItem;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.NonNestedProxyNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedPane;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphEditPart;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.policies.NullLayoutEditPolicy;
+import org.eclipse.mylar.zest.core.internal.viewers.figures.NestedFigure;
+import org.eclipse.mylar.zest.core.internal.viewers.figures.PaneFigure;
+import org.eclipse.swt.widgets.Display;
+
+
+/**
+ * Extends GraphEditPart to allow moving and resizing of nodes.
+ * 
+ * @author Chris Callendar
+ */
+public class NestedGraphEditPart extends GraphEditPart  {
+	
+	NestedPane supplierPane = null;
+	NestedPane clientPane = null;
+	NestedPane mainNestedPane = null;
+	
+	/**
+	 * A class that takes a series of figures, and animates them to a final 
+	 * position.
+	 * @author Del Myers
+	 *
+	 */
+	//@tag zest(bug(152613-Client-Supplier(fix)))
+	//@tag zest(bug(150585-TopArcs(fix)))
+	private class FigureKeyFrameAnimator {
+		private ArrayList figures;
+		private ArrayList startBounds;
+		private ArrayList endBounds;
+		private ArrayList figureParents;
+		
+		FigureKeyFrameAnimator() {
+			figures = new ArrayList();
+			endBounds = new ArrayList();
+			figureParents = new ArrayList();
+			startBounds = new ArrayList();
+		}
+		
+		/**
+		 * Adds figures to be animated. The figures should be added in the
+		 * state that the animation should start at. The endBounds is where the
+		 * figures should end up, in absolute coordinates.
+		 * @param figures the figures to move.
+		 * @param endBounds where the figures should end up, in absolute coordinates.
+		 */
+		public void addFigures(IFigure[] figuresArray, Rectangle[] endBounds) {
+			if (figuresArray.length != endBounds.length) {
+				throw new IllegalArgumentException("Arrays of unequal length");
+			}
+
+			for (int i = 0; i < figuresArray.length; i++) {
+				IFigure figure = figuresArray[i];
+				this.endBounds.add(endBounds[i]);
+				figures.add(figure);
+				figureParents.add(figure.getParent());
+				startBounds.add(figure.getBounds());
+			}
+		}
+		
+		/**
+		 * Starts the animation, using the given number of steps. The current thread
+		 * will suspend until the animation is complete.
+		 * @param steps the number of steps to take.
+		 */
+		public void start(final int steps) {
+			Display.getCurrent().syncExec(new Runnable() {
+				public void run() {
+					//@tag zest(bug(153169-OccludedArcs(fix))) : use the animation layer
+					Layer feedBack = (Layer) getLayer(NestedGraphRootEditPart.ANIMATION_LAYER);
+					feedBack.setLayoutManager(new XYLayout());
+					//startBounds.clear();
+					for (int i = 0; i < figures.size(); i++) {
+						IFigure figure = (IFigure) figures.get(i);
+						Rectangle figureBounds = figure.getBounds();
+						figure.translateToAbsolute(figureBounds);
+						feedBack.translateToRelative(figureBounds);
+						//startBounds.add(figureBounds);
+						figure.getParent().remove(figure);
+						feedBack.add(figure);
+						figure.setBounds(figureBounds);
+					}
+					
+					for (int step = 0; step < steps; step++) {
+						for (int i = 0; i < figures.size(); i++) {
+							IFigure figure = (IFigure) figures.get(i);
+							Rectangle bounds = (Rectangle)endBounds.get(i);
+							feedBack.translateToRelative(bounds);
+							Rectangle cBounds = (Rectangle) startBounds.get(i);
+							int newX = (int)(((double)(step+1)*(bounds.x - cBounds.x))/((double)steps)) + cBounds.x;
+							int newY = (int)(((double)(step+1)*(bounds.y - cBounds.y))/((double)steps)) + cBounds.y;
+							int newHeight = (int)(((double)(step+1)*(bounds.height - cBounds.height))/((double)steps)) + cBounds.height;
+							int newWidth = (int)(((double)(step+1)*(bounds.width - cBounds.width))/((double)steps)) + cBounds.width;
+							Rectangle newBounds = new Rectangle(newX, newY, newWidth, newHeight);
+							figure.setBounds(newBounds);
+							figure.setOpaque(true);
+							figure.invalidate();
+							figure.revalidate();
+						}
+						getViewer().flush();
+						sleep(25);
+					}
+					
+				}
+			});
+
+		}
+		/**
+		 * Clears all data from this animator. Normally should be called after
+		 * start().
+		 */
+		public void clear() {
+			for (int i = 0; i < figures.size(); i++) {
+				Layer feedBack = (Layer) getLayer(NestedGraphRootEditPart.ANIMATION_LAYER);
+				IFigure figure = (IFigure) figures.get(i);
+				if (figure.getParent() == feedBack) {
+					feedBack.remove(figure);
+					Rectangle bounds = figure.getBounds();
+					IFigure parent = (IFigure) figureParents.get(i);
+					if (parent != null) {
+						parent.add(figure);
+						figure.translateToRelative(bounds);
+						figure.setBounds(bounds);
+						figure.invalidateTree();
+					}
+				}
+			}
+			figures.clear();
+			endBounds.clear();
+			figureParents.clear();
+			startBounds.clear();
+		}
+	}
+	
+	/**
+	 * Initializes the edit part.
+	 * @param allowOverlap If nodes are allowed to overlap
+	 * @param enforceBounds If nodes can be moved outside the bounds  If this is set to false
+	 * then scrollbars will appear.
+	 */
+	public NestedGraphEditPart( ) {
+		super();
+		supplierPane = new NestedPane(NestedPane.SUPPLIER_PANE);
+		clientPane = new NestedPane(NestedPane.CLIENT_PANE);
+		mainNestedPane = new NestedPane(NestedPane.MAIN_PANE);
+	
+	}	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphEditPart#createEditPolicies()
+	 */
+	protected void createEditPolicies() {
+		installEditPolicy(EditPolicy.LAYOUT_ROLE, new NullLayoutEditPolicy());
+	}
+	
+	/**
+	 * Upon activation, attach to the model element as a property change listener.
+	 */
+	public void activate() {
+		if (!isActive()) {
+			super.activate();
+			((IGraphItem)getCastedModel().getRootNode()).addPropertyChangeListener(this);
+		}
+	}	
+	
+	/**
+	 * Upon deactivation, detach from the model element as a property change listener.
+	 */
+	public void deactivate() {
+		if (isActive()) {
+			super.deactivate();
+			((IGraphItem)getCastedModel().getRootNode()).removePropertyChangeListener(this);
+		}
+	}	
+
+	
+	
+	//TODO: should we change this to getNestedGraphModel?
+	// and make the same method in GraphEditPart called getGraphModel?
+	public NestedGraphModel getCastedModel() {
+		return (NestedGraphModel)getModel();
+	}	
+	
+	public void setModel(Object model) {
+
+		super.setModel(model);
+		supplierPane.setModel(getCastedModel());
+		clientPane.setModel(getCastedModel());
+		mainNestedPane.setModel(getCastedModel());
+		
+	}
+
+	protected NestedPaneAreaEditPart getMainEditPart() {
+		return (NestedPaneAreaEditPart) getViewer().getEditPartRegistry().get(mainNestedPane);
+	}
+	
+	protected NestedPaneAreaEditPart getClientEditPart() {
+		return (NestedPaneAreaEditPart) getViewer().getEditPartRegistry().get(clientPane);
+	}
+	
+	protected NestedPaneAreaEditPart getSupplierEditPart() {
+		return (NestedPaneAreaEditPart) getViewer().getEditPartRegistry().get(supplierPane);
+	}
+	
+	public Rectangle getMainArea() {
+//		@tag zest(bug(152613-Client-Supplier(fix))) : the drawable area is in the client panel, not the whole pane.
+		return getMainFigure().getClientPanel().getClientArea().getCopy();
+	}
+	
+	public Rectangle getClientPaneArea() {
+//		@tag zest(bug(152613-Client-Supplier(fix))) : the drawable area is in the client panel, not the whole pane.
+		return getClientFigure().getClientPanel().getClientArea().getCopy();
+	}
+	
+	public Rectangle getSupplierPaneArea() {
+//		@tag zest(bug(152613-Client-Supplier(fix))) : the drawable area is in the client panel, not the whole pane.
+		return getSupplierFigure().getClientPanel().getClientArea().getCopy();
+	}
+	
+		
+	protected PaneFigure getClientFigure() {
+		return (PaneFigure) getClientEditPart().getFigure();
+	}
+	
+	protected PaneFigure getMainFigure() {
+		return (PaneFigure)getMainEditPart().getFigure();
+	}
+	
+	protected PaneFigure getSupplierFigure() {
+		return (PaneFigure)getSupplierEditPart().getFigure();
+	}
+	
+	/**
+	 * Creates a NestedFreeformLayer which contains the root NestedFigure.
+	 * This NestedFigure will have an up button in the top left if the
+	 * current node isn't the root node.
+	 */
+	static int layoutCount = 0;
+	protected IFigure createFigure() {	
+		Figure figure = new Figure();
+		figure.setLayoutManager(new AbstractLayout() {
+			
+			protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
+				// TODO Auto-generated method stub
+				return null;
+			}
+
+			public void layout(IFigure container) {
+//				@tag zest(bug(152613-Client-Supplier(fix))) : layout the panes according to thier closed/openned state.
+				PaneFigure supply;
+				PaneFigure main;
+				PaneFigure client;
+				try {
+					supply = (PaneFigure) getSupplierFigure();
+					main = (PaneFigure) getMainFigure();
+					client = (PaneFigure) getClientFigure();
+				} catch (Exception e) {
+					//there may be times when the figure is asked to layout before
+					//all the children are added. This will throw an exception.
+					return;
+				}
+				Rectangle parentBounds = container.getBounds();
+				
+				Dimension preferedSize = client.getPreferredSize();
+		
+				Dimension clientSize = new Dimension(
+						parentBounds.width, 
+						(client.isClosed()) ? preferedSize.height : parentBounds.height/4
+				);
+				
+				
+				preferedSize = supply.getPreferredSize();
+				Dimension supplySize = new Dimension(
+						parentBounds.width, 
+						(supply.isClosed()) ? preferedSize.height : parentBounds.height/4
+				);
+				
+				Rectangle mainBounds = new Rectangle(
+						parentBounds.x, 
+						parentBounds.y + supplySize.height,
+						parentBounds.width,
+						parentBounds.height - supplySize.height - clientSize.height
+				);
+				getCastedModel().setClientClosed(client.isClosed());
+				getCastedModel().setSupplierClosed(supply.isClosed());
+				supply.setBounds(new Rectangle(parentBounds.x, parentBounds.y, supplySize.width, supplySize.height));
+				main.setBounds(mainBounds);
+				client.setBounds(new Rectangle(parentBounds.x, mainBounds.y + mainBounds.height, clientSize.width, clientSize.height));
+			}
+			
+		} );
+		figure.setOpaque(true);
+		return figure;
+	}		
+	
+	
+	protected List getModelChildren() {
+		List list = new ArrayList();
+		list.add( supplierPane );
+		list.add( mainNestedPane );
+		list.add( clientPane );
+		return list;
+		//return super.getModelChildren();
+	}
+	
+	
+	/**
+	 * Zooms in on the given node.
+	 * The type of zooming (real, fake, expand) depends on the zoomStyle.
+	 * @param editPart
+	 */
+	public void zoomInOnNode(NestedGraphNodeEditPart editPart) {
+		if (editPart == null)
+			return;
+		
+		//Rectangle maxBounds = getMainArea();
+		Rectangle startBounds = editPart.getAbsoluteBounds();
+		getLayer(LayerConstants.FEEDBACK_LAYER).translateToRelative(startBounds);
+		//@tag zest(bug(153170-FilterArcs(fix)))
+		//@tag zest(bug(153169-OccludedArcs(fix))) : filter the arcs before animating.
+		filterConnections(editPart.getCastedModel(), true);
+
+		//hide the proxies before starting
+		hideProxies();
+		doExpandZoom(startBounds, 10, editPart);
+	}
+	
+	
+	/**
+	 * Hides all the proxies in the client/supplier panes
+	 */
+	private void hideProxies() {
+		List proxies = new LinkedList();
+		proxies.addAll(supplierPane.getChildren());
+		proxies.addAll(clientPane.getChildren());
+		for (Iterator i =proxies.iterator(); i.hasNext();) {
+			GraphicalEditPart part = 
+				(GraphicalEditPart) getViewer().getEditPartRegistry().get(i.next());
+			List connections = new LinkedList();
+			connections.addAll(part.getSourceConnections());
+			connections.addAll(part.getTargetConnections());
+			for (Iterator j = connections.iterator(); j.hasNext();) {
+				GraphicalEditPart conPart = (GraphicalEditPart) j.next();
+				conPart.getFigure().setVisible(false);
+			}
+			part.getFigure().setVisible(false);
+			
+		}
+		
+		
+	}
+
+	/**
+	 * If <code>filter</code> is true filters out the connections that don't have 
+	 * an end in a node that has <code>node</code> as an ancestor. Otherwise, 
+	 * displays all nodes. 
+	 * @param node the node to filter against
+	 * @param filter whether or not the connections should be filtered.
+	 */
+	//@tag zest(bug(153170-FilterArcs(fix))) : make sure that the arcs are filtered out if they should be inivisible.
+	public void filterConnections(NestedGraphModelNode node, boolean filter) {
+		List connections = node.getGraphModel().getConnections();
+		for (Iterator i = connections.iterator(); i.hasNext();) {
+			IGraphModelConnection conn = (IGraphModelConnection) i.next();
+			GraphicalEditPart part = (GraphicalEditPart) getViewer().getEditPartRegistry().get(conn);
+			if (part != null) {
+				if (!filter) {
+					part.getFigure().setVisible(true);
+					continue;
+				}
+				NestedGraphModelNode source = (NestedGraphModelNode) conn.getSource();
+				NestedGraphModelNode dest = (NestedGraphModelNode) conn.getDestination();
+				int sourceRel = node.getRelationshipBetweenNodes(source);
+				int destRel = node.getRelationshipBetweenNodes(dest);
+				boolean visible = (
+					((sourceRel == NestedGraphModelNode.ANCESTOR) ||
+					(sourceRel == NestedGraphModelNode.SAME_NODE)) &&
+					((destRel == NestedGraphModelNode.ANCESTOR) ||
+					(destRel == NestedGraphModelNode.SAME_NODE))
+				);
+				part.getFigure().setVisible(visible);
+			}
+		}
+	}
+
+	/**
+	 * Zooms out on the given node.  
+	 * The type of zooming (real, fake, collapse) depends on the zoomStyle.
+	 * @param editPart
+	 */
+	
+	public void zoomOutOnNode( NestedGraphNodeEditPart editPart) {
+		if (editPart == null)
+			return;
+		
+//		@tag zest(bug(153169-OccludedArcs(fix))) : using the animation layer requires start bounds to be relative.
+		Rectangle maxBounds = getMainArea().getCopy();
+		editPart.getFigure().translateToRelative(maxBounds);
+		Rectangle endBounds = editPart.getAbsoluteBounds();
+		doCollapseZoom(maxBounds, endBounds, 15, editPart);
+	}
+	
+	/**
+	 * Draws an expanding dotted rectangle figure around the node to give the impression
+	 * of zooming in.  The dotted rectangle starts at the center of the node.
+	 */
+	//@tag zest(bug(152613-Client-Supplier(fix))) : change this to use the FigureKeyFrameAnimator
+	//@tag zest(bug(153169-OccludedArcs(fix))) : using FigureKeyFrameAnimator forces animation onto the animation layer
+	private void doCollapseZoom(Rectangle startBounds, Rectangle endBounds, final int STEPS, NestedGraphNodeEditPart node) {
+		NestedFigure fig = (NestedFigure) node.getFigure();
+		FigureKeyFrameAnimator animator = new FigureKeyFrameAnimator();
+		fig.setBounds(startBounds);
+		animator.addFigures(new IFigure[] {fig}, new Rectangle[] {endBounds});
+		animator.start(STEPS);
+		animator.clear();
+	}
+	
+	/**
+	 * Draws an expanding dotted rectangle figure around the node to give the impression
+	 * of zooming in.  The dotted rectangle starts at the center of the node.
+	 */
+	private void doExpandZoom(Rectangle startBounds, final int STEPS, NestedGraphNodeEditPart node) {
+		
+		NestedFigure fig = (NestedFigure)node.getFigure();
+		FigureKeyFrameAnimator animator = new FigureKeyFrameAnimator();
+		addChildrenToAnimator(node, animator);
+		
+		getViewer().flush();
+		animator.start(STEPS);
+		
+		FigureKeyFrameAnimator focusAnimator = new FigureKeyFrameAnimator();
+		Rectangle endBounds = getMainArea();
+		fig.setOpaque(true);
+		
+		focusAnimator.addFigures(new IFigure[]{fig}, new Rectangle[]{endBounds});
+		focusAnimator.start(STEPS);
+		animator.clear();
+		focusAnimator.clear();
+		deleteProxies();
+	}
+	
+	/**
+	 * Animates the children of the given node to place them into the correct panes.
+	 * @param node the node to get the children of.
+	 */
+	private void addChildrenToAnimator(final NestedGraphNodeEditPart node, FigureKeyFrameAnimator animator) {
+		createProxies(node.getCastedModel(), animator);
+		/*List connectedTo = node.getCastedModel().getNodesConnectedTo();
+		GraphicalEditPart[] editPartArray = new GraphicalEditPart[connectedTo.size()];
+		IFigure[] figureArray = new IFigure[editPartArray.length];
+		for (int i = 0; i < connectedTo.size(); i++) {
+			NestedGraphModelNode to = (NestedGraphModelNode)connectedTo.get(i);
+			editPartArray[i] = ((GraphicalEditPart)to.getEditPart());
+			figureArray[i] = editPartArray[i].getFigure();
+		}
+				
+		Arrays.sort(figureArray, FigureGridLayout.SimpleComparator);
+		Rectangle[] boundss = FigureGridLayout.layoutInBounds(getClientPaneArea(), figureArray);
+		animator.addFigures(figureArray, boundss);
+		
+		List connectedFrom = node.getCastedModel().getNodesConnectedFrom();
+		editPartArray = new GraphicalEditPart[connectedFrom.size()];
+		figureArray = new IFigure[editPartArray.length];
+		for (int i = 0; i < connectedFrom.size(); i++) {
+			NestedGraphModelNode From = (NestedGraphModelNode)connectedFrom.get(i);
+			editPartArray[i] = ((GraphicalEditPart)From.getEditPart());
+			figureArray[i] = editPartArray[i].getFigure();
+		}
+				
+		Arrays.sort(figureArray, FigureGridLayout.SimpleComparator);
+		boundss = FigureGridLayout.layoutInBounds(getSupplierPaneArea(), figureArray);
+		animator.addFigures(figureArray, boundss);
+		*/
+	}
+	
+		
+	private void createProxies(NestedGraphModelNode node, FigureKeyFrameAnimator animator) {
+		List connections = node.getConnectionsTo();
+		HashMap nodeProxyMap = new HashMap();
+		GraphModel graph = node.getGraphModel();
+		HashMap nodeEditParts = new HashMap();
+		ArrayList figureList = new ArrayList();
+		
+		for (Iterator i = connections.iterator(); i.hasNext();) {
+			IGraphModelConnection conn = (IGraphModelConnection) i.next();
+			NestedGraphModelNode pn = (NestedGraphModelNode) conn.getDestination();
+			GraphicalEditPart part = findCurrentProxy(pn, true);
+			NonNestedProxyNode proxy = (NonNestedProxyNode) nodeProxyMap.get(pn);
+			if (proxy == null) {
+				proxy = graph.createProxyNode(pn);
+				nodeProxyMap.put(pn, proxy);
+				nodeEditParts.put(proxy, createProxyNodeEditPart(proxy, part));
+			}
+			graph.createProxyConnection(conn.getSource(), proxy, conn);
+			part = (GraphicalEditPart) nodeEditParts.get(proxy);
+			GraphicalEditPart destPart = (GraphicalEditPart) getViewer().getEditPartRegistry().get(conn.getDestination());
+			
+			//conn.getDestination().getEditPart().refresh();
+			if (destPart != null) {
+				destPart.refresh();
+			}
+			part.refresh();
+		}
+		//get the figures
+		for (Iterator i=nodeEditParts.values().iterator(); i.hasNext();) {
+			figureList.add(((GraphicalEditPart)i.next()).getFigure());
+		}
+		IFigure[] figureArray = (IFigure[])figureList.toArray(new IFigure[figureList.size()]);
+		Arrays.sort(figureArray, FigureGridLayout.SimpleComparator);
+		Rectangle[] boundss = FigureGridLayout.layoutInBounds(getClientPaneArea(), figureArray);
+		animator.addFigures(figureArray, boundss);
+		
+						
+		nodeProxyMap.clear();
+		nodeEditParts.clear();
+		connections = node.getConnectionsFrom();
+		for (Iterator i = connections.iterator(); i.hasNext();) {
+			IGraphModelConnection conn = (IGraphModelConnection) i.next();
+			NestedGraphModelNode pn = (NestedGraphModelNode) conn.getSource();
+			GraphicalEditPart part = findCurrentProxy(pn, false);
+			NonNestedProxyNode proxy = (NonNestedProxyNode) nodeProxyMap.get(pn);
+			if (proxy == null) {
+				proxy = graph.createProxyNode(pn);
+				nodeProxyMap.put(pn, proxy);
+				nodeEditParts.put(proxy, createProxyNodeEditPart(proxy, part));
+			}
+			graph.createProxyConnection(proxy, conn.getDestination(), conn);
+			part = (GraphicalEditPart) nodeEditParts.get(proxy);
+			GraphicalEditPart destPart = (GraphicalEditPart) getViewer().getEditPartRegistry().get(conn.getDestination());
+			
+			//conn.getDestination().getEditPart().refresh();
+			if (destPart != null) {
+				destPart.refresh();
+			}
+			part.refresh();
+		}
+		
+//		get the figures
+		figureList.clear();
+		for (Iterator i=nodeEditParts.values().iterator(); i.hasNext();) {
+			figureList.add(((GraphicalEditPart)i.next()).getFigure());
+		}
+		figureArray = (IFigure[])figureList.toArray(new IFigure[figureList.size()]);
+		Arrays.sort(figureArray, FigureGridLayout.SimpleComparator);
+		boundss = FigureGridLayout.layoutInBounds(getSupplierPaneArea(), figureArray);
+		animator.addFigures(figureArray, boundss);
+		
+	}
+
+	/**
+	 * Deletes proxies that were created on this edit part for animations.
+	 *
+	 */
+	private void deleteProxies() {
+		Object[] children = getChildren().toArray();
+		for (int i = 0; i < children.length; i++) {
+			Object child = children[i];
+			if (child instanceof NonNestedGraphProxyNodeEditPart) {
+				NonNestedGraphProxyNodeEditPart part = (NonNestedGraphProxyNodeEditPart)child;
+				getCastedModel().removeProxyNode(part.getCastedModel());
+				//make sure that it is a child of this part.
+				getContentPane().add(part.getFigure());
+				removeChild(part);
+			}
+		}
+	}
+	
+	/**
+	 * @param pn
+	 * @param b
+	 * @return
+	 */
+	private GraphicalEditPart findCurrentProxy(NestedGraphModelNode pn, boolean to) {
+		List nodes;
+		if (to) {
+			nodes = clientPane.getChildren();
+		} else {
+			nodes = supplierPane.getChildren();
+		}
+		for (Iterator i = nodes.iterator(); i.hasNext();) {
+			NonNestedProxyNode node = (NonNestedProxyNode) i.next();
+			if (node.getProxy() == pn) {
+				GraphicalEditPart part = (GraphicalEditPart) getViewer().getEditPartRegistry().get(node);
+				return part;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Creates a proxy for the given node, and bases the location on the given edit part. The edit
+	 * part that the proxy edit part is being based on will be hidden from view, unless its model
+	 * is the current focus node.
+	 * 
+	 * @param proxy
+	 * @return
+	 */
+	private GraphicalEditPart createProxyNodeEditPart(NonNestedProxyNode proxy, GraphicalEditPart baseEditPart) {
+		NonNestedGraphProxyNodeEditPart part = new NonNestedGraphProxyNodeEditPart();
+		part.setModel(proxy);
+		part.setParent(this);
+		this.addChild(part, -1);
+		part.activate();
+		getViewer().getEditPartRegistry().put(proxy, part);
+		if (baseEditPart == null)
+			baseEditPart = (GraphicalEditPart) getViewer().getEditPartRegistry().get(proxy.getProxy());//(GraphicalEditPart)proxy.getProxy().getEditPart();
+		IFigure figure = part.getFigure();
+		figure.setParent(getLayer(LayerConstants.FEEDBACK_LAYER));
+		getViewer().getVisualPartMap().put(figure, part);
+		if (baseEditPart != null) {
+			IFigure proxyFigure = baseEditPart.getFigure();
+			baseEditPart.deactivate();
+			if (proxyFigure != null) {
+				if (baseEditPart.getModel() != getCastedModel().getCurrentNode())
+					proxyFigure.setVisible(false);
+				Rectangle proxyBounds = proxyFigure.getBounds().getCopy();
+				proxyFigure.translateToAbsolute(proxyBounds);
+				figure.getParent().translateToRelative(proxyBounds);
+				figure.setBounds(proxyBounds);
+			}
+		}
+		return part;
+	}
+
+	/**
+	 * Convenience method for calling Thread.sleep
+	 * and catching the InterruptedException.
+	 * @param millis the number of milliseconds to sleep
+	 */
+	protected void sleep(long millis) {
+		try {
+			Thread.sleep(millis);
+		} catch (InterruptedException ignore) {}
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphEditPartFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphEditPartFactory.java
new file mode 100644
index 0000000..7861287
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphEditPartFactory.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts;
+
+import org.eclipse.gef.EditPart;
+import org.eclipse.mylar.zest.core.internal.gefx.ZestRootEditPart;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.NonNestedProxyNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.ProxyConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedPane;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphConnectionEditPart;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphEditPartFactory;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.ProxyConnectionEditPart;
+
+
+/**
+ * Creates the edit parts associated with the different models.
+ * @author Chris Callendar
+ */
+public class NestedGraphEditPartFactory extends GraphEditPartFactory {
+
+	private boolean enforceBounds = false;
+	
+	public NestedGraphEditPartFactory(ZestRootEditPart graphRootEditPart, boolean allowOverlap, boolean enforceBounds) {
+		super( graphRootEditPart );
+		this.enforceBounds = enforceBounds;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.EditPartFactory#createEditPart(org.eclipse.gef.EditPart, java.lang.Object)
+	 */
+	public EditPart createEditPart(EditPart context, Object model) {
+		EditPart editPart = null;
+		if (model instanceof NonNestedProxyNode){
+			editPart = new NonNestedGraphProxyNodeEditPart();
+		} else if (model instanceof ProxyConnection){
+			editPart = new ProxyConnectionEditPart();
+		} else if (model instanceof NestedGraphModelNode) {
+			editPart = new NestedGraphNodeEditPart(enforceBounds);
+		} else if (model instanceof NestedGraphModel) {
+			editPart = new NestedGraphEditPart();
+			//((NestedGraphModel)model).clearProxies();
+			graphRootEditPart.setModelRootEditPart(editPart);
+			
+		} else if (model instanceof IGraphModelConnection) {
+			editPart = new GraphConnectionEditPart();
+		} else if ( model instanceof NestedPane ) {
+			editPart = new NestedPaneAreaEditPart(((NestedPane)model).getPaneType(), ((NestedPane)model).isClosed());
+		
+		} else {
+			editPart = super.createEditPart(context, model);
+		}
+		editPart.setModel(model);
+		
+		return editPart;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphNodeEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphNodeEditPart.java
new file mode 100644
index 0000000..a6d1293
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphNodeEditPart.java
@@ -0,0 +1,332 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.draw2d.ActionEvent;
+import org.eclipse.draw2d.ActionListener;
+import org.eclipse.draw2d.Clickable;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Label;
+import org.eclipse.draw2d.MarginBorder;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.DragTracker;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.requests.LocationRequest;
+import org.eclipse.gef.tools.MarqueeDragTracker;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphNodeEditPart;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.NestedGraphViewerImpl;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.policies.NestedGraphXYLayoutEditPolicy;
+import org.eclipse.mylar.zest.core.internal.viewers.figures.AspectRatioScaledFigure;
+import org.eclipse.mylar.zest.core.internal.viewers.figures.NestedFigure;
+import org.eclipse.mylar.zest.core.internal.viewers.figures.PlusMinusFigure;
+import org.eclipse.mylar.zest.core.internal.viewers.trackers.SingleSelectionTracker;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Extends GraphNodeEditPart to add functionality specific to nested graph
+ * nodes.
+ * 
+ * @author Chris Callendar
+ */
+public class NestedGraphNodeEditPart extends GraphNodeEditPart implements ActionListener {
+
+	private boolean enforceBounds;
+	private Clickable upButton = null;
+	private Label label;
+
+	public NestedGraphNodeEditPart(boolean enforceBounds) {
+		super();
+		this.enforceBounds = enforceBounds;
+	}
+
+	/**
+	 * Gets the bounds of the figure and translates it to absolute coordinates.
+	 * 
+	 * @return Rectangle in absolute coordinates
+	 */
+	public Rectangle getAbsoluteBounds() {
+		Rectangle bounds = getFigure().getBounds().getCopy();
+		getFigure().translateToAbsolute(bounds);
+		return bounds;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphNodeEditPart#createEditPolicies()
+	 */
+	protected void createEditPolicies() {
+		super.createEditPolicies();
+		installEditPolicy(EditPolicy.LAYOUT_ROLE, new NestedGraphXYLayoutEditPolicy(true));
+	}
+	
+	
+	/**
+	 * Gets the drag tracker for this edit part.
+	 * If the selection occurs on the root node then a marquee tracker
+	 * is used, otherwise the default tracker is used.
+	 */
+	public DragTracker getDragTracker(Request request) {
+		if ( ((NestedFigure)getFigure()).isPointInLabel(((LocationRequest)request).getLocation()) ) {
+			// If the location where this selection happens is in the label
+			// The use a single selection tracker
+			return new SingleSelectionTracker(this);
+		}		
+		else if ( this.getCastedModel().isCurrent() ) {
+			//@tag zest(bug(153221-Marquee-Selection(fix))) : make sure that the location is inside the scaled figure.
+			AspectRatioScaledFigure sfig = ((NestedFigure)getFigure()).getScaledFigure();
+			Rectangle scaledBounds = ((NestedFigure)getFigure()).getScaledFigure().getBounds().getCopy();
+			sfig.translateToAbsolute(scaledBounds);
+			if (scaledBounds.contains(((LocationRequest)request).getLocation()))
+					return new MarqueeDragTracker();
+		}
+		return super.getDragTracker(request);
+	}
+
+	// TODO rename to getNestedGraphModel() ?
+	public NestedGraphModelNode getCastedModel() {
+		return (NestedGraphModelNode) getModel();
+	}
+	
+	
+	/**
+	 * Gets the scaled bounds for this nested graph edit part
+	 * @return
+	 */
+	public Rectangle getBounds() {
+		NestedFigure nestedFigure = (NestedFigure)getFigure();
+		return nestedFigure.getClientArea();
+	
+	}
+
+	
+	protected IFigure createFigureForModel() {
+
+		if (((NestedGraphModel) getCastedModel().getGraphModel()).getCurrentNode() == getCastedModel()) {
+			NestedGraphModel model = (NestedGraphModel) getCastedModel().getGraphModel();
+			NestedGraphModelNode current = model.getCurrentNode();
+
+			if (current == null) {
+				label = new Label("Root"); // shouldn't get here
+			} else {
+				label = new Label(current.getText(), current.getImage());
+				label.setFont(current.getFont());
+			}
+			//@tag zest(bug(151332-Colors(fix)))
+			//@tag bug(154256-ClientSupplySelect(fix)) : get the colors from the model
+			label.setBackgroundColor(current.getBackgroundColor());
+			label.setForegroundColor(current.getForegroundColor());
+
+			// add an up button in the top left corner of the figure
+			upButton = null;
+			ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
+			Label upLabel = new Label(sharedImages.getImage(ISharedImages.IMG_TOOL_UP));
+			upLabel.setBorder(new MarginBorder(1));
+			upButton = new Clickable(upLabel);
+			if (current != model.getRootNode()) {
+				upButton.addActionListener(this);
+			} else {
+				upButton.setVisible(false);
+			}
+			upButton.setRolloverEnabled(false);
+			upButton.setToolTip(new Label(" Up "));
+
+			NestedFigure figure = new NestedFigure(label, upButton, !enforceBounds);
+			figure.getScaledFigure().setVisible(true);
+
+			if (getViewer() instanceof NestedGraphViewerImpl) {
+				NestedGraphViewerImpl viewer = (NestedGraphViewerImpl) getViewer();
+				Dimension dim = viewer.getCanvasSize();
+				figure.setSize(dim);
+			}
+			return figure;
+		}
+
+		else {
+			if (getCastedModel() != null) {
+				NestedGraphModelNode node = getCastedModel();
+				label = new Label(node.getText(), node.getImage());
+				label.setFont(node.getFont());
+				label.setForegroundColor(node.getForegroundColor());
+				PlusMinusFigure plusMinus = null;
+				if (node.hasChildren()) {
+
+					plusMinus = new PlusMinusFigure(NestedGraphModelNode.PLUS_SIZE);
+					plusMinus.setBorder(new MarginBorder(2));
+					plusMinus.addActionListener(this);
+
+				}
+				NestedFigure nestedFigure = new NestedFigure(label, plusMinus);
+				nestedFigure.setBackgroundColor(node.getBackgroundColor());
+				nestedFigure.setNestedFiguresVisible(node.getChildrenVisible());
+				nestedFigure.setScale(node.getWidthScale(), node.getHeightScale());
+				figure = nestedFigure;
+				((NestedFigure)figure).getScaledFigure().setVisible(true);
+				figure.setBounds(new Rectangle(1,0,100,100));
+			} else {
+				figure = super.createFigureForModel();
+			}
+			return figure;
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getContentPane()
+	 */
+	public IFigure getContentPane() {
+		return ((NestedFigure)getFigure()).getScaledFigure();
+	}
+
+	/**
+	 * Returns a list of the children GraphModelNode object.
+	 * 
+	 * @see org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphNodeEditPart#getModelChildren()
+	 */
+	protected List getModelChildren() {
+		return getCastedModel().getChildren();
+	}
+	
+	/**
+	 * The scaled figure that child NestedFigures will be placed on.
+	 * @return scaled figure that child NestedFigures will be placed on.
+	 */
+	public AspectRatioScaledFigure getScaledFigure() {
+		for (Iterator i = getFigure().getChildren().iterator(); i.hasNext();) {
+			Object next = i.next();
+			if (next instanceof AspectRatioScaledFigure) return (AspectRatioScaledFigure) next;
+		}
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see ca.uvic.cs.zest.internal.springgraphviewer.parts.GraphNodeEditPart#performRequest(org.eclipse.gef.Request)
+	 */
+	public void performRequest(Request req) {
+
+		if (REQ_OPEN.equals(req.getType())) {
+			// DebugPrint.println("performRequest() Bounds: " +
+			// getFigure().getBounds() + "\t " + getCastedModel().getLocation()
+			// + ", " + getCastedModel().getSize());
+			// DebugPrint.println("performRequest() Scale: " +
+			// getCastedModel().getScale() + ", " +
+			// ((NestedFigure)getFigure()).getScale());
+			// if(true) return;
+
+			// If there are children, then go down into that layer
+			NestedGraphModel model = getGraphModel();
+			if ((model != null) && (getCastedModel().getChildren().size() > 0)) {
+				model.setCurrentNode(getCastedModel());
+				if (getViewer() instanceof NestedGraphViewerImpl) {
+					((NestedGraphViewerImpl) getViewer()).fireModelUpdate();
+				}
+			}
+		} else {
+			super.performRequest(req);
+		}
+	}
+
+	/**
+	 * Handles the
+	 * {@link org.eclipse.mylar.zest.core.internal.viewers.figures.PlusMinusFigure}
+	 * click events. Toggles whether the children are shown.
+	 * 
+	 * @see org.eclipse.draw2d.ActionListener#actionPerformed(org.eclipse.draw2d.ActionEvent)
+	 */
+	public void actionPerformed(ActionEvent event) {
+		if ( event.getSource() == upButton ) {
+			NestedGraphModel model = (NestedGraphModel)getCastedModel().getGraphModel();
+			model.goUp();
+			if (getViewer() instanceof NestedGraphViewerImpl) {
+				upButton.removeActionListener(this);
+				Display.getCurrent().asyncExec(new Runnable() {
+
+					public void run() {
+						// TODO Auto-generated method stub
+						((NestedGraphViewerImpl)getViewer()).fireModelUpdate();
+						//openNode();
+					}
+					
+				});
+			}
+			
+		}
+		else {
+			openNode();
+		}
+
+	}
+
+	private void openNode() {
+		// check connections
+		if (getViewer() instanceof NestedGraphViewerImpl) {
+			NestedFigure fig = (NestedFigure) getFigure();
+			boolean vis = !fig.getScaledFigure().isVisible();
+			fig.setNestedFiguresVisible(vis);
+			NestedGraphModelNode node = getCastedModel();
+			node.setChildrenVisible(vis);
+
+			NestedGraphViewerImpl viewer = (NestedGraphViewerImpl) getViewer();
+			if (vis) {
+				// do a grid layout on the children using the full area and
+				// then
+				// scale
+				// Rectangle bounds = getGraphModel().getMainArea();
+				viewer.doLayout(node, 500, 500);
+				viewer.checkScaling(node);
+				// if (node.getScale() != fig.getScale()) {
+				fig.setScale(node.getWidthScale(), node.getHeightScale());
+				// }
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see ca.uvic.cs.zest.internal.springgraphviewer.parts.GraphNodeEditPart#refreshVisuals()
+	 */
+	protected void refreshVisuals() {
+		super.refreshVisuals();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphNodeEditPart#refreshColors()
+	 */
+	protected void refreshColors() {
+		//@tag zest(bug(152393(fix))) : Set the label color when the foreground changes.
+		if (label != null) {
+			label.setForegroundColor(getCastedModel().getForegroundColor());
+			label.setBackgroundColor(getCastedModel().getBackgroundColor());
+		}
+		super.refreshColors();
+	}
+
+	/**
+	 * Gets the NestedGraphModel from the NestedGraphModelNode
+	 * 
+	 * @return NestedGraphModel
+	 */
+	private NestedGraphModel getGraphModel() {
+		NestedGraphModel model = (NestedGraphModel) getCastedModel().getGraphModel();
+		return model;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphRootEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphRootEditPart.java
new file mode 100644
index 0000000..bbf4f8a
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedGraphRootEditPart.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts;
+
+import org.eclipse.draw2d.ConnectionLayer;
+import org.eclipse.draw2d.FreeformLayer;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.LayeredPane;
+import org.eclipse.draw2d.StackLayout;
+import org.eclipse.draw2d.Viewport;
+import org.eclipse.draw2d.ViewportLayout;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.gef.LayerConstants;
+import org.eclipse.gef.editparts.GuideLayer;
+import org.eclipse.gef.editparts.LayerManager;
+import org.eclipse.mylar.zest.core.internal.gefx.GraphRootEditPart;
+import org.eclipse.mylar.zest.core.internal.gefx.ZestRootEditPart;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphEditPart;
+
+/**
+ * Extends GraphRootEditPart to add zooming support.
+ * Currently there are three methods of zoom: the first is to use the 
+ * ZoomMananger and do "real" zooming.  The second is to fake the zooming by drawing an
+ * expanding or collapsing rectangle around the object to give the impression of zooming.  The 
+ * third way is to expand or collapse the current rectangle.
+ * 
+ * @author Chris Callendar
+ */
+public class NestedGraphRootEditPart extends GraphRootEditPart
+		implements LayerConstants, ZestRootEditPart, LayerManager {
+	
+	protected static final Object ANIMATION_LAYER = "nested.graph.animation.layer";
+	protected GraphEditPart graphEditPart = null;
+	private LayeredPane innerLayers;
+	private LayeredPane printableLayers;
+
+	/**
+	 * Initializes the root edit part with the given zoom style.
+	 * This can be real zooming, fake zooming, or expand/collapse zooming.
+	 */
+	public NestedGraphRootEditPart( ) {
+		super();
+		
+	}
+	
+	/**
+	 * Gets the nested edit part
+	 * TODO: Remove this once the zoom in on node is moved to the NestedGraphEditPart or panes below that
+	 * @return
+	 */
+	public NestedGraphEditPart getNestedEditPart() {
+		return (NestedGraphEditPart)graphEditPart;
+	}
+	
+	/*
+	 * The contents' Figure will be added to the PRIMARY_LAYER.
+	 * @see org.eclipse.gef.GraphicalEditPart#getContentPane()
+	 *
+	public IFigure getContentPane() {
+		return getLayer(PRIMARY_LAYER);
+	}*/
+
+	/**
+	 * The root editpart does not have a real model.  The LayerManager ID is returned so that
+	 * this editpart gets registered using that key.
+	 * @see org.eclipse.gef.EditPart#getModel()
+	 */
+	public Object getModel() {
+		return LayerManager.ID;
+	}
+	
+	/**
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
+	 */
+	protected IFigure createFigure() {
+		Viewport viewport = new Viewport();
+		viewport.setLayoutManager(new ViewportLayout());
+		viewport.setContentsTracksHeight(true);
+		viewport.setContentsTracksWidth(true);
+		innerLayers = new LayeredPane();
+		//@tag zest.bug.156915-NestedShrink.fix : the layout has to allow for shrinking minimum widths and heights.
+		innerLayers.setLayoutManager(new StackLayout(){
+			public Dimension getMinimumSize(IFigure container, int w, int h) {
+				return new Dimension(w,h);
+			}
+		});
+		createLayers(innerLayers);
+		viewport.setContents(innerLayers);
+		return viewport;
+	}
+	
+
+	
+	/**
+	 * Creates the top-most set of layers on the given layered pane.
+	 * @param layeredPane the parent for the created layers
+	 */
+	protected void createLayers(LayeredPane layeredPane) {
+		layeredPane.add(getScaledLayers(), SCALABLE_LAYERS);
+		layeredPane.add(new LayeredPane(), PRIMARY_LAYER);
+		//@tag zest(bug(153169-OccludedArcs(fix))) : put an animation layer under the connection layers
+		layeredPane.add(new FeedbackLayer(), ANIMATION_LAYER);
+		layeredPane.add(new ConnectionLayer(), CONNECTION_LAYER);
+		layeredPane.add(new ConnectionLayer(), CONNECTION_FEEDBACK_LAYER);
+		layeredPane.add(new FreeformLayer(), HANDLE_LAYER);
+		layeredPane.add(new FeedbackLayer(), FEEDBACK_LAYER);
+		layeredPane.add(new GuideLayer(), GUIDE_LAYER);
+	}
+	
+	
+
+	/**
+	 * Sets the main edit part for the model. You should be able to 
+	 * fire changes off here and see the effect
+	 */
+	public void setModelRootEditPart(Object modelRootEditPart) {
+		this.graphEditPart = (GraphEditPart) modelRootEditPart;
+	}
+
+	/**
+	 * Returns the layer indicated by the key. Searches all layered panes.
+	 * @see LayerManager#getLayer(Object)
+	 */
+	public IFigure getLayer(Object key) {
+		if (innerLayers == null)
+			return null;
+		IFigure layer = innerLayers.getLayer(key);
+		if (layer != null)
+			return layer;
+		if (printableLayers == null)
+			return null;
+		return printableLayers.getLayer(key);
+	}
+	
+	class FeedbackLayer extends FreeformLayer {
+		FeedbackLayer() {
+			setEnabled(false);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#unregisterVisuals()
+	 */
+	 //@tag zest(bug(153466-NoNestedClientSupply(fix))) : make sure that all the visuals are deregistered before recreating the parts.
+	/*protected void unregisterVisuals() {
+		List children = getFigure().getChildren();
+		//remove all the child figures for the root, which
+		//don't necessarilly have edit parts.
+		for (int i = 0; i < children.size(); i++) {
+			IFigure child = (IFigure) children.get(i);
+			getViewer().getVisualPartMap().remove(child);
+		}
+		getViewer().getVisualPartMap().remove(figure);
+	}
+	
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractEditPart#unregisterModel()
+	 */
+	 //@tag zest(bug(153466-NoNestedClientSupply(fix))) : make sure that all edit parts are removed before creating new ones.
+	/*protected void unregisterModel() {
+		//force revmoval of the edit parts.
+		for (Iterator i = getChildren().iterator(); i.hasNext();) {
+			EditPart child = (EditPart) i.next();
+			child.removeNotify();
+		}
+		super.unregisterModel();
+	}*/
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedPaneAreaEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedPaneAreaEditPart.java
new file mode 100644
index 0000000..8268200
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NestedPaneAreaEditPart.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.draw2d.FreeformLayout;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.NonNestedProxyNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedPane;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.policies.NestedGraphRootLayoutEditPolicy;
+import org.eclipse.mylar.zest.core.internal.viewers.figures.PaneFigure;
+
+/**
+ * A nested pane area part will create one of three kinds of pane figures,
+ * depending on context. The types are NestedPane.SUPPLIER_PANE, NestedPane.CLIENT_PANE,
+ * or NestedPain.MAIN_PANE. The main pane contains the nested graph element that
+ * the user is currently focussed on. The supplier pane contains all nodes that
+ * have arcs running "from" that node "to" the focus node, or any of its children.
+ * The client pane contains all nodes that have arcs running "to" that node "from"
+ * the focus node or any of its children.
+ * 
+ * @author Ian bull
+ * @author Del Myers
+ */
+
+//@tag bug(152613-Client-Supplier(fix)) : creates the figures that will hold all the nodes.
+public class NestedPaneAreaEditPart extends AbstractGraphicalEditPart implements PropertyChangeListener {
+	
+	private int paneType = 0;
+	private boolean initialClostedState;
+	
+	/**
+	 * 
+	 * @param paneType one of three types: NestedPane.MAIN_PANE, NestedPane.CLIENT_PANE,
+	 * NestedPane.SUPPLIER_PANE.
+	 */
+	public NestedPaneAreaEditPart(int paneType, boolean initialClosedState) {
+		this.paneType = paneType;
+		//@tag bug(152613-Client-Supplier(fix)) : add an initial closed state so that the states can be carried accross new contents in the viewer.
+		this.initialClostedState = initialClosedState;
+	}
+	
+	protected IFigure createFigure() {
+		PaneFigure f = new PaneFigure(paneType);
+		switch (paneType) {
+		case NestedPane.MAIN_PANE:
+			f.getClientPanel().setLayoutManager(new FreeformLayout() {
+				protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
+					return null;
+				}
+				public void layout(IFigure container) {
+					if (container.getChildren().size() != 1) return;
+					IFigure figure = (IFigure) container.getChildren().get(0);
+					Rectangle bounds = container.getBounds().getCopy();
+					figure.translateToAbsolute(bounds);
+					figure.setBounds(bounds);
+				}
+			});
+		break;
+		}
+		f.setClosed(initialClostedState);
+		return f;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.SimpleRootEditPart#createEditPolicies()
+	 */
+	protected void createEditPolicies() {
+		//@tag zest(bug(152393-TopSelection(fix))) : add an edit policy to the EditPart which will create policies that don't allow the nodes to move.
+		installEditPolicy(EditPolicy.LAYOUT_ROLE, new NestedGraphRootLayoutEditPolicy());
+	}
+	
+	protected List getModelChildren() {
+		if (getCastedModel() == null) return Collections.EMPTY_LIST;
+		return getCastedModel().getChildren();
+	}
+	
+	protected NestedPane getCastedModel() {
+		return (NestedPane) getModel();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#activate()
+	 */
+	public void activate() {
+		getCastedModel().getModel().addPropertyChangeListener(this);
+		super.activate();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#deactivate()
+	 */
+	public void deactivate() {
+		getCastedModel().getModel().removePropertyChangeListener(this);
+		super.deactivate();
+	}
+
+	/* (non-Javadoc)
+	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+	 */
+	public void propertyChange(PropertyChangeEvent evt) {
+		if (GraphModel.NODE_PROXY_REMOVED_PROP.equals(evt.getPropertyName())) {
+			getCastedModel().removeProxy((NonNestedProxyNode) evt.getOldValue());
+			refreshChildren();
+		}
+		
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NonNestedGraphProxyNodeEditPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NonNestedGraphProxyNodeEditPart.java
new file mode 100644
index 0000000..20e44f2
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/parts/NonNestedGraphProxyNodeEditPart.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts;
+
+import java.beans.PropertyChangeListener;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.draw2d.ChopboxAnchor;
+import org.eclipse.draw2d.ConnectionAnchor;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Label;
+import org.eclipse.gef.ConnectionEditPart;
+import org.eclipse.gef.NodeEditPart;
+import org.eclipse.gef.Request;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.NonNestedProxyNode;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphNodeEditPart;
+import org.eclipse.mylar.zest.core.internal.viewers.figures.SimpleLabelBox;
+
+/**
+ * An edit part for duplicating model nodes visually, without duplicating them
+ * in the model. The duplicates are not nested.
+ * @author Del Myers
+ *
+ */
+//@tag zest(bug(153466-NoNestedClientSupply(fix))) : create an edit part for proxy nodes.
+//@tag zest(bug(154256-ClientSupplySelect(fix))) : make NonNestedGraphNodeEditPart extend GraphNodeEditPart so that colors will change.
+public class NonNestedGraphProxyNodeEditPart extends GraphNodeEditPart
+	implements NodeEditPart, PropertyChangeListener {
+	ConnectionAnchor anchor;
+	private Label label;
+	
+
+	public NonNestedProxyNode getCastedModel() {
+		return (NonNestedProxyNode)getModel();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphNodeEditPart#createFigureForModel()
+	 */
+	protected IFigure createFigureForModel() {
+		IGraphModelNode node = getCastedModel().getProxy();
+		SimpleLabelBox box = new SimpleLabelBox();
+		label = box.getLabel();
+		label.setFont(node.getFont());
+		label.setText(node.getText());
+		label.setIcon(node.getImage());
+		label.setForegroundColor(node.getForegroundColor());
+		box.setBackgroundColor(node.getBackgroundColor());
+		return box;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
+	 */
+	protected IFigure createFigure() {
+		return createFigureForModel();
+	}
+
+
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getSourceConnections()
+	 */
+	public List getModelSourceConnections() {
+		if (getCastedModel() == null) return Collections.EMPTY_LIST;
+		return getCastedModel().getSourceConnections();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getTargetConnections()
+	 */
+	public List getModelTargetConnections() {
+		if (getCastedModel() == null) return Collections.EMPTY_LIST;
+		return getCastedModel().getTargetConnections();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.NodeEditPart#getSourceConnectionAnchor(org.eclipse.gef.ConnectionEditPart)
+	 */
+	public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection) {
+		return getDefaultAnchor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.NodeEditPart#getSourceConnectionAnchor(org.eclipse.gef.Request)
+	 */
+	public ConnectionAnchor getSourceConnectionAnchor(Request request) {
+		return getDefaultAnchor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.NodeEditPart#getTargetConnectionAnchor(org.eclipse.gef.ConnectionEditPart)
+	 */
+	public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connection) {
+		return getDefaultAnchor();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.NodeEditPart#getTargetConnectionAnchor(org.eclipse.gef.Request)
+	 */
+	public ConnectionAnchor getTargetConnectionAnchor(Request request) {
+		return getDefaultAnchor();
+	}
+	
+	protected ConnectionAnchor getDefaultAnchor() {
+		if (anchor == null) {
+			anchor = new ChopboxAnchor(getFigure());
+		}
+		return anchor;
+	}
+
+
+
+	/**
+	 * Refreshes the figures colors from the model.  This includes the border color and width.
+	 */
+	protected void refreshColors() {
+		IFigure figure = getFigure();
+		IGraphModelNode model = getCastedModel();
+		figure.setForegroundColor(model.getForegroundColor());
+		figure.setBackgroundColor(model.getBackgroundColor());
+		
+		if (label != null) {
+			label.setForegroundColor(model.getForegroundColor());
+			label.setBackgroundColor(model.getBackgroundColor());
+		}
+		
+		//this.getFigure().revalidate();	
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#activate()
+	 */
+	public void activate() {
+		if (!isActive()) {
+			refreshVisuals();
+			refreshSourceConnections();
+			refreshTargetConnections();
+			super.activate();
+			//we need to listen to the proxy.
+			//getCastedModel().getProxy().addPropertyChangeListener(this);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#deactivate()
+	 */
+	public void deactivate() {
+		super.deactivate();
+		if (!isActive()) {
+			//getCastedModel().getProxy().removePropertyChangeListener(this);
+		}
+	}
+		
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/policies/ColorSelectionEditPolicy.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/policies/ColorSelectionEditPolicy.java
new file mode 100644
index 0000000..2c6f586
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/policies/ColorSelectionEditPolicy.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer.policies;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.gef.editpolicies.ResizableEditPolicy;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphNodeEditPart;
+
+
+/**
+ * The ColorSelectionEditPolicy uses a different color for the selected object.
+ * When an edit part is selected the edit part fires of a highlight property change event,
+ * and when the selection is hidden the unhighlight property event is fired.
+ * 
+ * @author Chris Callendar
+ */
+public class ColorSelectionEditPolicy extends ResizableEditPolicy {
+
+	private GraphNodeEditPart editPart;
+	
+	/**
+	 * ColorSelectionEditPolicy constructor.
+	 */
+	//@tag bug(154256-ClientSupplySelect(fix)) : let it take a regular node edit part.
+	public ColorSelectionEditPolicy(GraphNodeEditPart editPart) {
+		this.editPart = editPart;
+ 	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.SelectionEditPolicy#hideSelection()
+	 */
+	protected void hideSelection() {
+		super.hideSelection();
+		//@tag bug(154256-ClientSupplySelect(fix)) : let the model take care of it.
+		((IGraphModelNode)editPart.getModel()).unhighlight();
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.SelectionEditPolicy#showSelection()
+	 */
+	protected void showSelection() {
+		super.showSelection();
+		//@tag bug(154256-ClientSupplySelect(fix)) : let the model take care of it.
+		((IGraphModelNode)editPart.getModel()).highlight();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.NonResizableEditPolicy#showChangeBoundsFeedback(org.eclipse.gef.requests.ChangeBoundsRequest)
+	 */
+	protected void showChangeBoundsFeedback(ChangeBoundsRequest request) {
+		super.showChangeBoundsFeedback(request);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.NonResizableEditPolicy#eraseChangeBoundsFeedback(org.eclipse.gef.requests.ChangeBoundsRequest)
+	 */
+	protected void eraseChangeBoundsFeedback(ChangeBoundsRequest request) {
+		super.eraseChangeBoundsFeedback(request);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ResizableEditPolicy#createSelectionHandles()
+	 */
+	protected List createSelectionHandles() {
+		//@tag zest.bug.152393-TopSelection.fix : no handles on the top-level nodes.
+		Object model = editPart.getModel();
+		if (model instanceof NestedGraphModelNode) {
+			NestedGraphModelNode node = (NestedGraphModelNode) model;
+			if (node == ((NestedGraphModel)node.getGraphModel()).getCurrentNode()) {
+				return Collections.EMPTY_LIST;
+			}
+		}
+		return super.createSelectionHandles();
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/policies/NestedGraphRootLayoutEditPolicy.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/policies/NestedGraphRootLayoutEditPolicy.java
new file mode 100644
index 0000000..3c75ffe
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/policies/NestedGraphRootLayoutEditPolicy.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer.policies;
+
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.gef.requests.CreateRequest;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphNodeEditPart;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts.NestedGraphNodeEditPart;
+
+/**
+ * Creates a constrained edit policy for root-level nested graph nodes.
+ * @author Del Myers
+ */
+//@tag bug(152393-TopSelection(fix)) : this edit policy simply creates a command that doesn't allow any movement of the nodes.
+public class NestedGraphRootLayoutEditPolicy extends ConstrainedLayoutEditPolicy {
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#createChangeConstraintCommand(org.eclipse.gef.requests.ChangeBoundsRequest, org.eclipse.gef.EditPart, java.lang.Object)
+	 */
+	protected Command createChangeConstraintCommand(ChangeBoundsRequest request, EditPart child, Object constraint) {
+		if (child instanceof NestedGraphNodeEditPart && constraint instanceof Rectangle) {
+			return new Command() {
+				/* (non-Javadoc)
+				 * @see org.eclipse.gef.commands.Command#canExecute()
+				 */
+				public boolean canExecute() {
+					return false;
+				}
+				
+				/* (non-Javadoc)
+				 * @see org.eclipse.gef.commands.Command#canUndo()
+				 */
+				public boolean canUndo() {
+					return false;
+				}
+			};
+		}
+		return super.createChangeConstraintCommand(request, child, constraint);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#createChildEditPolicy(org.eclipse.gef.EditPart)
+	 */
+	protected EditPolicy createChildEditPolicy(EditPart child) {
+		if (child instanceof GraphNodeEditPart) {
+			return new ColorSelectionEditPolicy((GraphNodeEditPart)child);
+		}
+		return super.createChildEditPolicy(child);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#createChangeConstraintCommand(org.eclipse.gef.EditPart, java.lang.Object)
+	 */
+	protected Command createChangeConstraintCommand(EditPart child, Object constraint) {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.LayoutEditPolicy#getCreateCommand(org.eclipse.gef.requests.CreateRequest)
+	 */
+	protected Command getCreateCommand(CreateRequest request) {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#getConstraintFor(org.eclipse.draw2d.geometry.Point)
+	 */
+	protected Object getConstraintFor(Point point) {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#getConstraintFor(org.eclipse.draw2d.geometry.Rectangle)
+	 */
+	protected Object getConstraintFor(Rectangle rect) {
+		return null;
+	}
+	
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/policies/NestedGraphXYLayoutEditPolicy.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/policies/NestedGraphXYLayoutEditPolicy.java
new file mode 100644
index 0000000..05f3cb6
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/policies/NestedGraphXYLayoutEditPolicy.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer.policies;
+
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.Request;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.editpolicies.XYLayoutEditPolicy;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.gef.requests.CreateRequest;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts.NestedGraphNodeEditPart;
+import org.eclipse.mylar.zest.core.internal.viewers.commands.ResizeNodeConstraintCommand;
+
+
+
+/**
+ * Extends XYLayoutEditPolicy to use a child color selection policy (which allows resizing), and to get create and delete 
+ * commands.  Can also choose if overlapping is allowed (not allowed by default).
+ * 
+ * @author Chris Callendar
+ */
+public class NestedGraphXYLayoutEditPolicy extends XYLayoutEditPolicy {
+	
+	private boolean enforceBounds = false;
+	
+	public NestedGraphXYLayoutEditPolicy(boolean enforceBounds) {
+		this.enforceBounds = enforceBounds;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#createAddCommand(org.eclipse.gef.EditPart, java.lang.Object)
+	 */
+	protected Command createAddCommand(EditPart child, Object constraint) {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#createChildEditPolicy(org.eclipse.gef.EditPart)
+	 */
+	protected EditPolicy createChildEditPolicy(EditPart child) {
+		if (child instanceof NestedGraphNodeEditPart) {
+			return new ColorSelectionEditPolicy((NestedGraphNodeEditPart)child);
+		}
+		return super.createChildEditPolicy(child);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#createChangeConstraintCommand(org.eclipse.gef.requests.ChangeBoundsRequest, org.eclipse.gef.EditPart, java.lang.Object)
+	 */
+	protected Command createChangeConstraintCommand(ChangeBoundsRequest request, EditPart child, Object constraint) {
+		if ((child instanceof NestedGraphNodeEditPart) && (constraint instanceof Rectangle)) {
+			NestedGraphNodeEditPart editPart = (NestedGraphNodeEditPart)child;
+			//System.out.println("req: " + request.getLocation() + "\t" + request.getSizeDelta() + "\t" + constraint);
+			ResizeNodeConstraintCommand cmd = new ResizeNodeConstraintCommand(editPart, (NestedGraphModelNode)editPart.getModel(), request, (Rectangle)constraint);
+			cmd.setEnforceBounds(enforceBounds);
+			return cmd;
+		}
+		return super.createChangeConstraintCommand(request, child, constraint);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#createChangeConstraintCommand(org.eclipse.gef.EditPart, java.lang.Object)
+	 */
+	protected Command createChangeConstraintCommand(EditPart child, Object constraint) {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.LayoutEditPolicy#getCreateCommand(org.eclipse.gef.requests.CreateRequest)
+	 */
+	protected Command getCreateCommand(CreateRequest request) {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.LayoutEditPolicy#getDeleteDependantCommand(org.eclipse.gef.Request)
+	 */
+	protected Command getDeleteDependantCommand(Request request) {
+		return null;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/policies/NullLayoutEditPolicy.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/policies/NullLayoutEditPolicy.java
new file mode 100644
index 0000000..8cc0e47
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/nestedgraphviewer/policies/NullLayoutEditPolicy.java
@@ -0,0 +1,59 @@
+package org.eclipse.mylar.zest.core.internal.nestedgraphviewer.policies;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy;
+import org.eclipse.gef.editpolicies.SelectionHandlesEditPolicy;
+import org.eclipse.gef.requests.CreateRequest;
+
+/**
+ * A null-edit policy doesn't allow figures to be moved, or resized in the layout.
+ * @author Del Myers
+ *
+ */
+//@tag bug(152613-Client-Supplier(fix)) : disallow anything top-level from being moved around
+public final class NullLayoutEditPolicy extends ConstrainedLayoutEditPolicy {
+	protected Command createChangeConstraintCommand(EditPart child, Object constraint) {
+		return createCommand();
+	}
+
+	protected Object getConstraintFor(Point point) {
+		return null;
+	}
+
+	protected Object getConstraintFor(Rectangle rect) {
+		return null;
+	}
+
+	protected Command getCreateCommand(CreateRequest request) {
+		return createCommand();
+	}
+
+	private Command createCommand() {
+		return new Command(){
+			public boolean canExecute() {
+				return false;
+			}
+			public boolean canUndo() {
+				return false;
+			}
+		};
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editpolicies.ConstrainedLayoutEditPolicy#createChildEditPolicy(org.eclipse.gef.EditPart)
+	 */
+	protected EditPolicy createChildEditPolicy(EditPart child) {
+		return new SelectionHandlesEditPolicy(){
+			protected List createSelectionHandles() {
+				return Collections.EMPTY_LIST;
+			}
+		};
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/BranchLayout.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/BranchLayout.java
new file mode 100644
index 0000000..a16319b
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/BranchLayout.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import java.util.List;
+
+import org.eclipse.draw2d.AbstractLayout;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.geometry.Transposer;
+
+/**
+ * This was originally a Draw2D Snippet that has been modified for Zest. All bugs 
+ * in this should be opened against the Zest project.
+ * 
+ * @author hudsonr Created on Apr 22, 2003
+ * @author Ian Bull
+ */
+public abstract class BranchLayout extends AbstractLayout {
+
+	private Transposer transposer;
+	final TreeBranch branch;
+	int[] cachedContourLeft;
+	int[] cachedContourRight;
+	int depth = -1;
+	public boolean horizontal = true;
+	int[] preferredRowHeights;
+	int rowHeight;
+
+	public BranchLayout(TreeBranch branch) {
+		this.branch = branch;
+	}
+
+	abstract void calculateDepth();
+
+	public int[] getContourLeft() {
+		if (cachedContourLeft == null)
+			updateContours();
+		return cachedContourLeft;
+	}
+
+	public int[] getContourRight() {
+		if (cachedContourRight == null)
+			updateContours();
+		return cachedContourRight;
+	}
+
+	public int getDepth() {
+		if (!branch.isExpanded())
+			return 1;
+		if (depth == -1)
+			calculateDepth();
+		return depth;
+	}
+
+	public int[] getPreferredRowHeights() {
+		if (preferredRowHeights == null)
+			updateRowHeights();
+		return preferredRowHeights;
+	}
+
+	List getSubtrees() {
+		return branch.getContentsPane().getChildren();
+	}
+
+	Transposer getTransposer() {
+		if (transposer == null)
+			transposer = branch.getRoot().getTransposer();
+		return transposer;
+	}
+
+	int getMajorSpacing() {
+		return branch.getRoot().getMajorSpacing();
+	}
+
+	public void invalidate() {
+		preferredRowHeights = null;
+		cachedContourLeft = null;
+		cachedContourRight = null;
+		depth = -1;
+		super.invalidate();
+	}
+
+	public boolean isHorizontal() {
+		return horizontal;
+	}
+
+	abstract void paintLines(Graphics g);
+
+	public void setHorizontal(boolean value) {
+		horizontal = value;
+	}
+
+	void setRowHeights(int heights[], int offset) {
+		if (rowHeight != heights[offset]) {
+			rowHeight = heights[offset];
+			branch.revalidate();
+		}
+	}
+
+	abstract void updateContours();
+
+	abstract void updateRowHeights();
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/DagModelFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/DagModelFactory.java
new file mode 100644
index 0000000..e9b6c3b
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/DagModelFactory.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright 2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.mylar.zest.core.viewers.IDAGContentProvider;
+import org.eclipse.swt.SWT;
+
+/**
+ * 
+ * @author Ian Bull
+ */
+public class DagModelFactory {
+
+	ILabelProvider labelProvider = null;
+	DagViewerImpl viewerImpl = null;
+	IDAGContentProvider dagContentProvider = null;
+	
+	Map itemMap = null;
+	
+	public DagModelFactory( DagViewerImpl dagViewerImpl,
+							IDAGContentProvider dagContentProvider,
+							ILabelProvider labelProvider ) {
+		this.dagContentProvider = dagContentProvider;
+		this.viewerImpl = dagViewerImpl;
+		this.labelProvider = labelProvider;
+		itemMap = new HashMap();
+	}
+	
+	public DagNode[] createModel(Object[] elements) {
+		if ( elements == null ) return new DagNode[0];
+		
+		ArrayList dagNodeList = new ArrayList(); 
+		for (int i = 0; i < elements.length; i++) {
+			DagNode node = createRoot(elements[i]);
+			if ( node != null ) {
+				dagNodeList.add(node);
+				createChildren(node, elements[i]);
+			}
+		}
+		return (DagNode[])dagNodeList.toArray(new DagNode[dagNodeList.size()]);
+	}
+	
+	private void createChildren(DagNode parent, Object element) {
+		Object[] children = this.dagContentProvider.getAdjacent(element);
+		if ( children == null ) return;
+		for (int i = 0; i < children.length; i++) {
+			Object currentChild = children[i];
+			DagNode childBranch = createBranch(parent, currentChild);
+			if ( childBranch != null ) {
+				createChildren(childBranch, currentChild);
+			}
+		}
+	}
+	
+	private DagNode createBranch(DagNode parent, Object o) {
+		if ( itemMap.containsKey(o) ) {
+			parent.addConnectedNode((DagNode) itemMap.get(o));
+			return null;
+		}
+		String label = labelProvider.getText(o);
+		int hangingStyle = viewerImpl.getHangingStyle() ? TreeBranch.STYLE_HANGING : TreeBranch.STYLE_NORMAL;
+		DagNode branch = new DagNode(parent, SWT.NONE, o, label,viewerImpl, hangingStyle);
+		parent.addConnectedNode(branch);
+		itemMap.put(o, branch);
+		return branch;
+	}
+
+	private DagNode createRoot(Object o) {
+		if ( itemMap.containsKey(o) ) {
+			return null;
+		}
+		String label = labelProvider.getText(o);
+		int hangingStyle = viewerImpl.getHangingStyle() ? TreeBranch.STYLE_HANGING : TreeBranch.STYLE_NORMAL;
+		DagNode root = new DagNode(viewerImpl, SWT.NONE, o, label,viewerImpl, hangingStyle);
+		itemMap.put(o, root);
+		return root;
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/DagNode.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/DagNode.java
new file mode 100644
index 0000000..5631024
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/DagNode.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright 2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.draw2d.ChopboxAnchor;
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.MouseEvent;
+import org.eclipse.draw2d.MouseListener;
+import org.eclipse.draw2d.MouseMotionListener;
+import org.eclipse.draw2d.PolylineConnection;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Widget;
+
+public class DagNode extends Item {
+
+	private ArrayList connectedNodes = null; // List of connected nodes
+	private ArrayList instanceNodes = null; // These are all the places this dag
+	private String text;
+	private DagViewerImpl viewer = null;
+	private int initialHangingStyle = 0;
+
+	// private boolean selected = false;
+
+	public DagNode(Widget parent, int style, Object element, String text,
+			DagViewerImpl viewer, int initialHangingStyle) {
+		super(parent, style);
+		this.setData(element);
+		this.text = text;
+		this.viewer = viewer;
+		this.initialHangingStyle = initialHangingStyle;
+		this.instanceNodes = new ArrayList();
+		connectedNodes = new ArrayList();
+
+	}
+
+	public void addConnectedNode(DagNode node) {
+		connectedNodes.add(node);
+	}
+
+	public int getInitialHangingStyle() {
+		return this.initialHangingStyle;
+	}
+
+	void placeFigure(IFigure f, DagNode parentNode) {
+		DagBranch branch = new DagBranch(text, connectedNodes, this);
+		instanceNodes.add(branch);
+		f.add(branch);
+	}
+
+	public void showConnectedSelected(DagBranch dagItem) {
+		Iterator iterator = instanceNodes.iterator();
+		while (iterator.hasNext()) {
+			DagBranch item = (DagBranch) iterator.next();
+			if (item != dagItem) {
+				PolylineConnection polylineConnection = new PolylineConnection();
+				IFigure a = dagItem.getNode();
+				IFigure b = item.getNode();
+				polylineConnection.setSourceAnchor(new ChopboxAnchor(a));
+				polylineConnection.setTargetAnchor(new ChopboxAnchor(b));
+				polylineConnection.setLineWidth(1);
+				viewer.getConnectionLayer().add(polylineConnection);
+				polylineConnection.setBackgroundColor(ColorConstants.lightGray);
+				polylineConnection.setForegroundColor(ColorConstants.lightGray);
+			}
+		}
+	}
+
+	public void placeFigure(IFigure f) {
+		DagBranch root = new DagBranch(text, connectedNodes, this);
+		instanceNodes.add(root);
+		f.add(root);
+
+	}
+
+	DagViewerImpl getViewer() {
+		return this.viewer;
+	}
+
+	public void setSelected(boolean b) {
+		// this.selected = b;
+		Iterator iterator = instanceNodes.iterator();
+		while (iterator.hasNext()) {
+			DagBranch dagRoot = (DagBranch) iterator.next();
+			dagRoot.getNode().setSelected(b);
+		}
+	}
+}
+
+class DagBranch extends TreeRoot {
+
+	List connectedNodes = null;
+	DagNode correspondindDagNode = null;
+	boolean expanded = false;
+
+	public DagBranch(String text, List connectedNodes, DagNode dagNode) {
+		super(text);
+		this.connectedNodes = connectedNodes;
+		this.correspondindDagNode = dagNode;
+		this.setStyle(dagNode.getInitialHangingStyle());
+
+		this.addExpandListener(new ExpandListener() {
+			public void collapse(TreeBranch branch) {
+			}
+
+			public void expand(TreeBranch branch) {
+				if (!expanded) {
+					for (int i = 0; i < DagBranch.this.connectedNodes.size(); i++) {
+						DagNode node = (DagNode) DagBranch.this.connectedNodes
+								.get(i);
+						node.placeFigure(DagBranch.this.getContentsPane(),
+								DagBranch.this.correspondindDagNode);
+					}
+				}
+				expanded = true;
+			}
+		});
+
+		this.addMouseListener(new MouseListener.Stub() {
+			public void mousePressed(MouseEvent me) {
+				correspondindDagNode.getViewer().setSelected(
+						DagBranch.this.correspondindDagNode);
+				DagBranch.this.correspondindDagNode
+						.showConnectedSelected(DagBranch.this);
+			}
+
+			public void mouseDoubleClicked(MouseEvent me) {
+
+			}
+		});
+		this.addMouseMotionListener(new MouseMotionListener() {
+
+			public void mouseDragged(MouseEvent me) {
+				// TODO Auto-generated method stub
+
+			}
+
+			public void mouseEntered(MouseEvent me) {
+				correspondindDagNode.getViewer().highlightNode(DagBranch.this);
+			}
+
+			public void mouseExited(MouseEvent me) {
+				correspondindDagNode.getViewer().unHighlightNode();
+			}
+
+			public void mouseHover(MouseEvent me) {
+				// TODO Auto-generated method stub
+
+			}
+
+			public void mouseMoved(MouseEvent me) {
+				// TODO Auto-generated method stub
+
+			}
+
+		});
+
+	}
+
+	protected boolean hasChildren() {
+		return connectedNodes.size() > 0;
+	}
+
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/DagViewerImpl.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/DagViewerImpl.java
new file mode 100644
index 0000000..b1035ff
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/DagViewerImpl.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright 2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.FlowLayout;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.LayoutAnimator;
+import org.eclipse.draw2d.StackLayout;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.core.viewers.IDAGContentProvider;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+
+public class DagViewerImpl extends Canvas {
+
+	private FigureCanvas figureCanvas = null;
+	private IFigure regularLayer = null;
+	private IFigure connectionLayer = null;
+	private boolean treeCompression = false;
+	private boolean hangingStyle = false;
+
+	private DagNode selected;
+	private DagBranch highlighted;
+
+	public DagViewerImpl(Composite parent, int style) {
+		super(parent, style);
+		
+		if ( (style & ZestStyles.TREE_GRAPH_COMPRESS) > 0 ) {
+			// @tag style(tree_graph(compress))
+			treeCompression = true;
+		}
+		if ( (style & ZestStyles.TREE_GRAPH_HANGING_LAYOUT ) > 0 ) {
+			// @tag style(tree_graph(hanging))
+			hangingStyle = true;
+		}
+		this.setLayout(new FillLayout());
+		figureCanvas = new FigureCanvas(this);
+		figureCanvas.setLayout(new FillLayout());	
+	}
+	
+	private FigureCanvas getFigureCanvas() {
+		return figureCanvas;
+	}
+	
+	public boolean getTreeCompression() {
+		return this.treeCompression;
+	}
+	
+	public boolean getHangingStyle() {
+		return hangingStyle;
+	}
+	
+	public IFigure getConnectionLayer() {
+		return connectionLayer;
+	}
+
+	public void setContents(Object input, IDAGContentProvider contentProvider, ILabelProvider labelProvider) {
+		getFigureCanvas().setBackground(ColorConstants.white);
+		connectionLayer = new Figure();
+		regularLayer = new Figure();
+		
+		IFigure f = new Figure();
+		
+		StackLayout stackLayout = new StackLayout();
+		f.addLayoutListener(LayoutAnimator.getDefault());
+		f.setLayoutManager(stackLayout);
+		
+		FlowLayout flowLayout = new FlowLayout(false);
+		flowLayout.setMinorAlignment(FlowLayout.ALIGN_LEFTTOP);
+		
+		regularLayer.setLayoutManager(flowLayout);
+		connectionLayer.setLayoutManager(stackLayout);
+		
+		DagModelFactory factory = new DagModelFactory(this, contentProvider, labelProvider);
+		DagNode[] roots = factory.createModel(contentProvider.getElements(input));
+		for (int i = 0; i < roots.length; i++) {
+			roots[i].placeFigure(regularLayer);
+			//roots[i].setCompression(treeCompression);
+		}
+		f.add(connectionLayer);
+		f.add(regularLayer);
+		getFigureCanvas().setContents(f);
+	}
+
+	
+	void unHighlightNode() {
+		if ( highlighted != null ) {
+			highlighted.getNode().setHighlighted(false);
+		}
+	}
+	void highlightNode(DagBranch dagBranch ) {
+		if ( highlighted != null ) {
+			highlighted.getNode().setHighlighted(false);
+		}
+		highlighted = dagBranch;
+		dagBranch.getNode().setHighlighted(true);
+	}
+	
+	void setSelected(DagNode dagNode) {
+		if (selected != null) {
+			selected.setSelected(false);
+		}
+		// Remove all the old connections
+		while ( connectionLayer.getChildren().size() > 0 ) {
+			connectionLayer.remove((IFigure)connectionLayer.getChildren().get(0));
+		}
+		selected = dagNode;
+		selected.setSelected(true);
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/ExpandListener.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/ExpandListener.java
new file mode 100644
index 0000000..0036901
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/ExpandListener.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright 2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+/**
+ * 
+ * @author Ian Bull
+ *
+ */
+public interface ExpandListener {
+
+	public void expand(TreeBranch branch);
+	public void collapse(TreeBranch branch);	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/HangingLayout.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/HangingLayout.java
new file mode 100644
index 0000000..b7fedcd
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/HangingLayout.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import java.util.List;
+
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.draw2d.geometry.Transposer;
+
+/**
+ * This was originally a Draw2D Snippet that has been modified for Zest. All bugs 
+ * in this should be opened against the Zest project.
+ * 
+ * @author hudsonr Created on Apr 22, 2003
+ * @author Ian Bull
+ */
+class HangingLayout extends BranchLayout {
+
+	HangingLayout(TreeBranch branch) {
+		super(branch);
+	}
+
+	void calculateDepth() {
+		depth = 0;
+		List subtrees = branch.contents.getChildren();
+		for (int i = 0; i < subtrees.size(); i++)
+			depth += ((TreeBranch) subtrees.get(i)).getDepth();
+		depth++;
+	}
+
+	void setRowHeights(int[] heights, int offset) {
+		super.setRowHeights(heights, offset);
+		offset++;
+		if (branch.isExpanded()) {
+			List subtrees = branch.contents.getChildren();
+			TreeBranch subtree;
+
+			for (int i = 0; i < subtrees.size(); i++) {
+				subtree = (TreeBranch) subtrees.get(i);
+				subtree.setRowHeights(heights, offset);
+				offset += subtree.getDepth();
+			}
+		}
+	}
+
+	/**
+	 * @see org.eclipse.draw2d.examples.tree.BranchLayout#updateRowHeights()
+	 */
+	void updateRowHeights() {
+		Transposer transposer = branch.getRoot().getTransposer();
+		preferredRowHeights = new int[getDepth()];
+		preferredRowHeights[0] = transposer.t(branch.getNode().getPreferredSize()).height + getMajorSpacing();
+		if (!branch.isExpanded())
+			return;
+
+		List subtrees = getSubtrees();
+		TreeBranch subtree;
+
+		int offset = 1;
+		for (int i = 0; i < subtrees.size(); i++) {
+			subtree = (TreeBranch) subtrees.get(i);
+			int rowHeights[] = subtree.getPreferredRowHeights();
+			for (int row = 0; row < rowHeights.length; row++)
+				preferredRowHeights[row + offset] = rowHeights[row];
+			offset += subtree.getDepth();
+		}
+	}
+
+	int getGap() {
+		return branch.getRoot().getMinorSpacing();
+	}
+
+	protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
+		Transposer transposer = branch.getRoot().getTransposer();
+		Dimension result = transposer.t(branch.getNode().getPreferredSize().getCopy());
+		result.height = rowHeight;
+		IFigure pane = branch.getContentsPane();
+		if (!pane.isVisible() || pane.getChildren().isEmpty())
+			return transposer.t(result);
+		Dimension d = transposer.t(branch.getContentsPane().getPreferredSize());
+		result.width = Math.max(result.width, d.width + getGap() * 2);
+		result.height += d.height;
+		return transposer.t(result);
+	}
+
+
+	public void layout(IFigure f) {
+		
+		branch.getContentsPane().validate();
+
+		Transposer transposer = getTransposer();
+		Rectangle clientArea = new Rectangle();
+		branch.getClientArea(clientArea);
+		clientArea = transposer.t(clientArea);
+		Rectangle nodeBounds = new Rectangle();
+		
+		nodeBounds.setSize(transposer.t(branch.getNode().getPreferredSize()));
+		nodeBounds.height = rowHeight - getMajorSpacing();
+		nodeBounds.setLocation(clientArea.x, clientArea.y);
+		branch.getNode().setBounds(transposer.t(nodeBounds));
+		
+		IFigure contents = branch.getContentsPane();
+		Rectangle contentsBounds = new Rectangle(clientArea.getLocation().translate(getGap() * 2, rowHeight),
+				transposer.t(contents.getPreferredSize()));
+		contents.setBounds(transposer.t(contentsBounds));	
+	}
+	
+
+	/**
+	 * @see org.eclipse.draw2d.examples.tree.BranchLayout#paintLines(org.eclipse.draw2d.Graphics)
+	 */
+	void paintLines(Graphics g) {
+		int gap = getGap();
+		g.setLineWidth(2);
+		if (getTransposer().isEnabled()) {
+			IFigure node = branch.getNode();
+			IFigure contents = branch.getContentsPane();
+			int x = node.getBounds().right();
+			int y = node.getBounds().y + gap;
+			List children = contents.getChildren();
+			if (children.size() == 0)
+				return;
+			int right = x;
+			for (int i = 0; i < children.size(); i++) {
+				Point pt = ((TreeBranch) children.get(i)).getNodeBounds().getTop();
+				g.drawLine(pt.x, y, pt.x, pt.y);
+				right = Math.max(right, pt.x);
+			}
+			g.drawLine(x, y, right, y);
+
+		} else {
+			IFigure node = branch.getNode();
+			IFigure contents = branch.getContentsPane();
+			int x = node.getBounds().x + gap;
+			int y = node.getBounds().bottom();
+			List children = contents.getChildren();
+			if (children.size() == 0)
+				return;
+			int bottom = y;
+			for (int i = 0; i < children.size(); i++) {
+				Point pt = ((TreeBranch) children.get(i)).getNodeBounds().getLeft();
+				g.drawLine(x, pt.y, pt.x, pt.y);
+				bottom = Math.max(bottom, pt.y);
+			}
+			
+			g.drawLine(x, y, x, bottom);
+		}
+	}
+
+	void updateContours() {
+		// Make sure we layout first
+		Transposer transposer = getTransposer();
+		branch.validate();
+
+		cachedContourLeft = new int[getDepth()];
+		cachedContourRight = new int[getDepth()];
+
+		Rectangle clientArea = transposer.t(branch.getClientArea(Rectangle.SINGLETON));
+		Rectangle nodeBounds = transposer.t(branch.getNodeBounds());
+		int rightEdge = clientArea.right();
+
+		cachedContourLeft[0] = nodeBounds.x - clientArea.x;
+		cachedContourRight[0] = rightEdge - nodeBounds.right();
+
+		if (!branch.isExpanded())
+			return;
+
+		List subtrees = branch.contents.getChildren();
+		TreeBranch subtree;
+
+		int leftSide = getGap();
+		for (int i = 1; i < getDepth(); i++)
+			cachedContourLeft[i] = leftSide;
+
+		int rightMargin;
+		int offset = 1;
+		for (int i = 0; i < subtrees.size(); i++) {
+			subtree = (TreeBranch) subtrees.get(i);
+			rightMargin = rightEdge - transposer.t(subtree.getBounds()).right();
+			int rightContour[] = subtree.getContourRight();
+			for (int j = 0; j < rightContour.length; j++)
+				cachedContourRight[j + offset] = rightContour[j] + rightMargin;
+			offset += subtree.getDepth();
+		}
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/NormalLayout.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/NormalLayout.java
new file mode 100644
index 0000000..ee83d49
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/NormalLayout.java
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import java.util.List;
+
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.draw2d.geometry.Transposer;
+
+/**
+ * This was originally a Draw2D Snippet that has been modified for Zest. All bugs 
+ * in this should be opened against the Zest project.
+ * 
+ * @author hudsonr Created on Apr 22, 2003
+ * @author Ian Bull
+ */
+class NormalLayout extends BranchLayout {
+
+NormalLayout(TreeBranch branch) {
+	super(branch);
+}
+
+/**
+ * @see org.eclipse.draw2d.examples.tree.BranchLayout#calculateDepth()
+ */
+void calculateDepth() {
+	depth = 0;
+	List subtrees = getSubtrees();
+	for (int i = 0; i < subtrees.size(); i++)
+		depth = Math.max(depth, ((TreeBranch)subtrees.get(i)).getDepth());
+	depth++;
+}
+
+protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
+	Rectangle union = branch.getNodeBounds().getCopy();
+	union.union(branch.getContentsPane().getBounds());
+	return union.getSize();
+}
+
+public void layout(IFigure f) {
+
+	Transposer transposer = getTransposer();
+	IFigure contents = branch.getContentsPane();
+	IFigure node = branch.getNode();
+	contents.validate();
+
+	Rectangle branchBounds = transposer.t(branch.getBounds());
+	Point topLeft = branchBounds.getTopLeft();
+	Rectangle nodeLocation = new Rectangle(topLeft, transposer.t(node.getPreferredSize()));
+	nodeLocation.height = rowHeight - getMajorSpacing();
+	
+	if (!contents.isVisible() || contents.getChildren().isEmpty()) {
+		nodeLocation.x += (branchBounds.width - nodeLocation.width)/2;
+		node.setBounds(transposer.t(nodeLocation));
+		contents.setBounds(
+			transposer.t(nodeLocation.getTranslated(0, rowHeight).setSize(0, 0)));
+		return;
+	}
+
+	Rectangle contentsLocation =
+		new Rectangle(topLeft, transposer.t(contents.getPreferredSize()));
+	contents.setSize(contents.getPreferredSize());
+	contentsLocation.y += rowHeight;
+
+	TreeBranch firstChild = (TreeBranch)contents.getChildren().get(0);
+	TreeBranch lastChild =
+		(TreeBranch)contents.getChildren().get(contents.getChildren().size() - 1);
+	int leftInset =
+		firstChild.getContourLeft()[0]
+			+ transposer.t(firstChild.getBounds()).x
+			- transposer.t(contents.getBounds()).x;
+	int rightInset =
+		lastChild.getContourRight()[0]
+			- transposer.t(lastChild.getBounds()).right()
+			+ transposer.t(contents.getBounds()).right();
+	rightInset = Math.max(rightInset, 0);
+	leftInset = Math.max(leftInset, 0);
+	int childrenSpan = contentsLocation.width - leftInset - rightInset;
+
+	switch (branch.getAlignment()) {
+		case PositionConstants.CENTER :
+			leftInset += (childrenSpan - nodeLocation.width) / 2;
+	}
+
+	if (leftInset > 0)
+		nodeLocation.x += leftInset;
+	else
+		contentsLocation.x -= leftInset;
+	
+	int adjust =
+		branchBounds.width
+			- Rectangle.SINGLETON.setBounds(contentsLocation).union(nodeLocation).width;
+	adjust /= 2;
+	nodeLocation.x += adjust;
+	contentsLocation.x += adjust;
+	node.setBounds(transposer.t(nodeLocation));
+	contents.setBounds(transposer.t(contentsLocation));
+
+}
+
+void mergeContour(int[] destination, int[] source, int startdepth, int offset) {
+	for (int i = startdepth; i<source.length; i++)
+		destination[i+1] = source[i] + offset;
+}
+
+/**
+ * @see org.eclipse.draw2d.examples.tree.BranchLayout#paintLines(org.eclipse.draw2d.Graphics)
+ */
+void paintLines(Graphics g) {
+	if (getTransposer().isEnabled()) {
+		IFigure node = branch.getNode();
+		int left = node.getBounds().right();
+		int right = branch.getContentsPane().getBounds().x - 1;
+		int yMid = node.getBounds().getCenter().y;
+		int xMid = (left + right) / 2;
+		List children = getSubtrees();
+		if (children.size() == 0)
+			return;
+		g.setLineWidth(2);
+		g.drawLine(left, yMid, xMid, yMid);
+		int yMin = yMid;
+		int yMax = yMid;
+		for (int i=0; i<children.size(); i++){
+			int y = ((TreeBranch)children.get(i)).getNodeBounds().getCenter().y;
+			g.drawLine(xMid, y, right, y);
+			yMin = Math.min(yMin, y);
+			yMax = Math.max(yMax, y);
+		}
+		
+		g.drawLine(xMid, yMin, xMid, yMax);
+
+	} else {
+		IFigure node = branch.getNode();
+		int xMid = node.getBounds().getCenter().x;
+		int top = node.getBounds().bottom();
+		int bottom = branch.getContentsPane().getBounds().y - 1;
+		int yMid = (top + bottom) / 2;
+		List children = getSubtrees();
+		if (children.size() == 0)
+			return;
+		g.setLineWidth(2);
+		g.drawLine(xMid, top, xMid, yMid);
+		int xMin = xMid;
+		int xMax = xMid;
+		for (int i=0; i<children.size(); i++){
+			int x = ((TreeBranch)children.get(i)).getNodeBounds().getCenter().x;
+			g.drawLine(x, yMid, x, bottom);
+			xMin = Math.min(xMin, x);
+			xMax = Math.max(xMax, x);
+		}
+		g.drawLine(xMin, yMid, xMax, yMid);
+	}
+}
+
+/**
+ * @see org.eclipse.draw2d.examples.tree.BranchLayout#updateContours()
+ */
+void updateContours() {
+	Transposer transposer = getTransposer();
+	//Make sure we layout first
+	branch.validate();
+
+	cachedContourLeft = new int[getDepth()];
+	cachedContourRight = new int[getDepth()];
+
+	Rectangle clientArea =
+		transposer.t(branch.getNodeBounds().getUnion(branch.contents.getBounds()));
+	Rectangle nodeBounds = transposer.t(branch.getNodeBounds());
+	transposer.t(branch.getContentsPane().getBounds());
+	
+	cachedContourLeft[0] = nodeBounds.x - clientArea.x;
+	cachedContourRight[0] = clientArea.right() - nodeBounds.right();
+	if (!branch.isExpanded())
+		return;
+
+	List subtrees = getSubtrees();
+	TreeBranch subtree;
+
+	int currentDepth = 0;
+	for (int i = 0; i < subtrees.size() && currentDepth < getDepth(); i++) {
+		subtree = (TreeBranch)subtrees.get(i);
+		if (subtree.getDepth() > currentDepth) {
+			int leftContour[] = subtree.getContourLeft();
+			int leftOffset = transposer.t(subtree.getBounds()).x - clientArea.x;
+			mergeContour(cachedContourLeft, leftContour, currentDepth, leftOffset);
+			currentDepth = subtree.getDepth();
+		}
+	}
+
+	currentDepth = 0;
+	for (int i = subtrees.size() - 1; i >= 0 && currentDepth < getDepth(); i--) {
+		subtree = (TreeBranch)subtrees.get(i);
+		if (subtree.getDepth() > currentDepth) {
+			int rightContour[] = subtree.getContourRight();
+			int rightOffset =
+				clientArea.right() - transposer.t(subtree.getBounds()).right();
+			mergeContour(cachedContourRight, rightContour, currentDepth, rightOffset);
+			currentDepth = subtree.getDepth();
+		}
+	}
+}
+
+/**
+ * @see org.eclipse.draw2d.examples.tree.BranchLayout#updateRowHeights()
+ */
+void updateRowHeights() {
+	Transposer transposer = getTransposer();
+	preferredRowHeights = new int[getDepth()];
+
+	preferredRowHeights[0] =
+		transposer.t(branch.getNode().getPreferredSize()).height + getMajorSpacing();
+
+	if (!branch.isExpanded())
+		return;
+
+	List subtrees = getSubtrees();
+	TreeBranch subtree;
+	
+	for (int i = 0; i < subtrees.size(); i++) {
+		subtree = (TreeBranch)subtrees.get(i);
+		int rowHeights[] = subtree.getPreferredRowHeights();
+		for (int row = 0; row < rowHeights.length; row++)
+			preferredRowHeights[row + 1] =
+				Math.max(preferredRowHeights[row + 1], rowHeights[row]);
+	}
+}
+
+/**
+ * @see org.eclipse.draw2d.examples.tree.BranchLayout#setRowHeights(int[], int)
+ */
+void setRowHeights(int[] heights, int offset) {
+	super.setRowHeights(heights, offset);
+	if (branch.isExpanded()) {
+		List subtrees = getSubtrees();
+		offset++;
+		for (int i=0; i<subtrees.size(); i++)
+			((TreeBranch)subtrees.get(i)).setRowHeights(heights, offset);
+	}
+}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/PageNode.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/PageNode.java
new file mode 100644
index 0000000..3784a4a
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/PageNode.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import org.eclipse.draw2d.AbstractBorder;
+import org.eclipse.draw2d.ActionListener;
+import org.eclipse.draw2d.Border;
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.CompoundBorder;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.FlowLayout;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Label;
+import org.eclipse.draw2d.LayoutAnimator;
+import org.eclipse.draw2d.MarginBorder;
+import org.eclipse.draw2d.geometry.Insets;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * This was originally a Draw2D Snippet that has been modified for Zest. All bugs 
+ * in this should be opened against the Zest project.
+ * 
+ * @author hudsonr Created on Apr 22, 2003
+ * @author Ian Bull
+ */
+public class PageNode extends Figure {
+
+	private boolean selected;
+	private boolean highlighted;
+	static final Color gradient1 = new Color(null, 232, 232, 240);
+	static final Color gradient2 = new Color(null, 176, 184, 216);
+	static final Color corner1 = new Color(null, 200, 208, 223);
+	static final Color corner2 = new Color(null, 160, 172, 200);
+	static final Color blue = new Color(null, 152, 168, 200);
+	//static final Font font = new Font()  Look below where I create the font... do this in a registy
+	static final Color shadow = new Color(null, 202, 202, 202);
+	static final int CORNER_SIZE = 10;
+	static final Border BORDER = new CompoundBorder(new FoldedPageBorder(), new MarginBorder(0, 2,1, 10));
+
+	private PlusMinus plusMinus = new PlusMinus();
+	private TreeStyle layoutDisplay = null; 
+	
+	static class FoldedPageBorder extends AbstractBorder {
+		static final PointList CORNER_ERASE;
+
+		static final PointList CORNER_PAINT;
+		
+		static {
+			CORNER_ERASE = new PointList(3);
+			CORNER_ERASE.addPoint(1, 0);
+			CORNER_ERASE.addPoint(1, CORNER_SIZE + 1);
+			CORNER_ERASE.addPoint(-CORNER_SIZE, 0);
+			CORNER_PAINT = new PointList(3);
+			CORNER_PAINT.addPoint(-CORNER_SIZE, 0);
+			CORNER_PAINT.addPoint(0, CORNER_SIZE);
+			CORNER_PAINT.addPoint(-CORNER_SIZE, CORNER_SIZE);
+			
+		}
+		
+
+		static final Insets insets = new Insets(CORNER_SIZE, 2, 4, 4);
+
+		public Insets getInsets(IFigure figure) {
+			return insets;
+		}
+
+		public void paint(IFigure figure, Graphics g, Insets insets) {
+			Rectangle r = getPaintRectangle(figure, insets);
+			g.setLineWidth(4);
+			r.resize(-2, -2);
+			g.setForegroundColor(shadow);
+			g.drawLine(r.x + 3, r.bottom(), r.right() - 1, r.bottom());
+			g.drawLine(r.right(), r.y + 3 + CORNER_SIZE, r.right(), r.bottom() - 1);
+			g.restoreState();
+			r.resize(-1, -1);
+			g.drawRectangle(r);
+			g.setForegroundColor(blue);
+			g.drawRectangle(r.x + 1, r.y + 1, r.width - 2, r.height - 2);
+			g.translate(r.getTopRight());
+			g.fillPolygon(CORNER_ERASE);
+			g.setBackgroundColor(corner1);
+			g.fillPolygon(CORNER_PAINT);
+			g.setForegroundColor(figure.getForegroundColor());
+			g.drawPolygon(CORNER_PAINT);
+			g.restoreState();
+			g.setForegroundColor(corner2);
+			g.drawLine(r.right() - CORNER_SIZE + 1, r.y + 2, r.right() - 2, r.y + CORNER_SIZE - 1);
+		}
+	}
+
+	private Label label = new Label();
+
+	public PageNode(String text) {
+		this();
+		FontData[] fd = Display.getDefault().getSystemFont().getFontData();
+		fd[0].height= 9;
+		label.setFont(new Font(Display.getDefault(), fd));
+		label.setText(text);
+		
+	}
+
+	public PageNode() {
+		this.addLayoutListener(LayoutAnimator.getDefault());
+		layoutDisplay = new TreeStyle(this);
+		setBorder(BORDER);
+
+		FlowLayout flowLayout = new FlowLayout(false);
+		flowLayout.setMajorSpacing(0);
+		flowLayout.setMinorSpacing(0);
+		setLayoutManager(flowLayout);
+		
+		layoutDisplay.setBounds(new Rectangle(0,0,-1,-1));
+
+		IFigure top = new Figure();
+		top.setLayoutManager(new FlowLayout(true));
+		top.add(plusMinus);
+		top.add(layoutDisplay);
+		add(top);
+		add(label);
+	}
+	
+	public void addClickChangeListener( ActionListener listener ) {
+		plusMinus.addActionListener(listener);
+	}
+	
+	public void layoutChangedListener( ActionListener listener ) {
+		layoutDisplay.addActionListener(listener);
+	}
+	
+	public boolean isSelected() {
+		return this.selected;
+	}
+	
+	public void setHasChildren(boolean hasChildren) {
+//		plusMinus.setVisible(hasChildren);
+//		layoutDisplay.setVisible(hasChildren);
+		plusMinus.setVisible(hasChildren);
+		layoutDisplay.setVisible(hasChildren);
+	}
+	
+	public void setExpanded(boolean expanded) {
+		plusMinus.setSelected(expanded);
+	}
+	
+	public void setHangingLayoutStyle(boolean hanging) {
+		layoutDisplay.setSelected(hanging);
+	}
+
+	public Insets getInsets() {
+		Insets currentInsets = super.getInsets();
+		currentInsets.top = 3;
+		return currentInsets;
+	}
+	
+	/**
+	 * @see org.eclipse.draw2d.Figure#paintFigure(org.eclipse.draw2d.Graphics)
+	 */
+	protected void paintFigure(Graphics g) {
+		super.paintFigure(g);
+		if (selected) {
+			g.setForegroundColor(ColorConstants.menuBackgroundSelected);
+			g.setBackgroundColor(ColorConstants.titleGradient);
+		} else if (highlighted) {
+			g.setForegroundColor(blue);
+			g.setBackgroundColor(corner1);
+		}
+		else {
+			g.setForegroundColor(gradient1);
+			g.setBackgroundColor(gradient2);
+		}
+		g.fillGradient(getBounds().getResized(-3, -3), true);
+
+	}
+	
+	public void setHighlighted(boolean value) {
+		this.highlighted = value;
+		repaint();
+	}
+
+	public void setSelected(boolean value) {
+		this.selected = value;
+		if (selected)
+			label.setForegroundColor(ColorConstants.white);
+		else
+			label.setForegroundColor(null);
+		repaint();
+	}
+
+
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/PlusMinus.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/PlusMinus.java
new file mode 100644
index 0000000..8d889a1
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/PlusMinus.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Toggle;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+/**
+ * This was originally a Draw2D Snippet that has been modified for Zest. All bugs 
+ * in this should be opened against the Zest project.
+ * 
+ * @author hudsonr Created on Apr 22, 2003
+ * @author Ian Bull
+ */
+public class PlusMinus extends Toggle {
+
+	{
+		setPreferredSize(9, 9);
+	}
+
+
+	
+	/**
+	 * @see org.eclipse.draw2d.Figure#paintFigure(org.eclipse.draw2d.Graphics)
+	 */
+	protected void paintFigure(Graphics g) {
+		super.paintFigure(g);
+		g.setBackgroundColor(ColorConstants.black);
+		g.setForegroundColor(ColorConstants.black);
+		Rectangle r = Rectangle.SINGLETON;
+		r.setBounds(getBounds()).resize(-1, -1);
+		g.drawRectangle(r);
+		int xMid = r.x + r.width / 2;
+		int yMid = r.y + r.height / 2;
+		g.drawLine(r.x + 2, yMid, r.right() - 2, yMid);
+		if (!isSelected()) {
+			g.drawLine(xMid, r.y + 2, xMid, r.bottom() - 2);
+		}
+	}
+
+	
+	
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeBranch.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeBranch.java
new file mode 100644
index 0000000..385625a
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeBranch.java
@@ -0,0 +1,441 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.draw2d.ActionEvent;
+import org.eclipse.draw2d.ActionListener;
+import org.eclipse.draw2d.Animation;
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.FreeformLayout;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Layer;
+import org.eclipse.draw2d.LayoutAnimator;
+import org.eclipse.draw2d.LayoutManager;
+import org.eclipse.draw2d.LineBorder;
+import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.draw2d.ToolbarLayout;
+import org.eclipse.draw2d.Viewport;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+/**
+ * This was originally a Draw2D Snippet that has been modified for Zest. All bugs 
+ * in this should be opened against the Zest project.
+ * 
+ * @author hudsonr Created on Apr 22, 2003
+ * @author Ian Bull
+ */
+public class TreeBranch extends Figure {
+	public static final int ANIMATION_TIME = 200;
+	List expandListeners = new LinkedList();
+
+	class AnimatingLayer extends Layer {
+		
+		public AnimatingLayer() {
+			this.addLayoutListener(LayoutAnimator.getDefault());
+			this.setOpaque(false);
+		}
+
+		
+		/**
+		 * @see org.eclipse.draw2d.Figure#setBounds(org.eclipse.draw2d.geometry.Rectangle)
+		 */
+		public void setBounds(Rectangle rect) {			
+			int x = bounds.x, y = bounds.y;
+
+			
+			boolean resize = (rect.width != bounds.width) || (rect.height != bounds.height), 
+				translate = (rect.x != x)|| (rect.y != y);
+
+			if (isVisible() && (resize || translate))
+				erase();
+			if (translate) {
+				int dx = rect.x - x;
+				int dy = rect.y - y;
+				primTranslate(dx, dy);
+			}
+			bounds.width = rect.width;
+			bounds.height = rect.height;
+			// if (resize) Layouts dont depend on size.
+			// invalidate();
+			if (resize || translate) {
+				fireFigureMoved();
+				repaint();
+			}
+		}
+		
+		public void layout() {
+			super.layout();
+		}
+
+	}
+
+	public static final int STYLE_HANGING = 1;
+	public static final int STYLE_NORMAL = 2;
+	int aligment = PositionConstants.LEFT;
+
+	/*
+	 * A layer is being used simply because it is the only "transparent" figure
+	 * in draw2d. See the implementation of Layer.containsPoint(...) for what is
+	 * meant by "transparent". If a layer is not used, then overlapping branches
+	 * will cause hit-test problems.
+	 */
+	AnimatingLayer contents = new AnimatingLayer();
+	boolean expanded = false;
+	PageNode node;
+	int style;
+	
+	public TreeBranch( String label ) {
+		this(new PageNode(label));
+	}
+
+	public TreeBranch(PageNode title) {
+		this(title, STYLE_NORMAL);
+	}
+
+	public TreeBranch(PageNode title, int style) {
+		this.setLayoutManager(new NormalLayout(this));
+		this.addLayoutListener(LayoutAnimator.getDefault());
+		if (title.getBorder() == null)
+			title.setBorder(new LineBorder(ColorConstants.gray, 2));
+		this.node = title;
+		
+		setStyle(style);
+		this.setExpanded(expanded);
+		
+		this.node.addClickChangeListener(new ActionListener() {
+			public void actionPerformed(ActionEvent event) {
+				
+				
+				if ( isExpanded() ) collapse();
+				else expand();
+				
+				
+			}
+		});
+		this.node.layoutChangedListener(new ActionListener() {
+
+			public void actionPerformed(ActionEvent event) {
+				Animation.markBegin();
+				TreeStyle plusMinusEvent = (TreeStyle) event.getSource();
+				if ( plusMinusEvent.isSelected() )
+					setStyle(TreeBranch.STYLE_HANGING);
+				else 
+					setStyle(TreeBranch.STYLE_NORMAL);
+				Animation.run(ANIMATION_TIME);
+			}
+			
+		});
+		add(contents);
+		add(title);
+	}
+
+	/**
+	 * recursively set all nodes and sub-treebranch nodes to the same location.
+	 * This gives the appearance of all nodes coming from the same place.
+	 * 
+	 * @param bounds
+	 *            where to set
+	 */
+	public void animationReset(Rectangle bounds) {
+		List subtrees = contents.getChildren();
+		contents.setBounds(bounds);
+
+		// Make the center of this node match the center of the given bounds
+		Rectangle r = node.getBounds();
+		int dx = bounds.x + bounds.width / 2 - r.x - r.width / 2;
+		int dy = bounds.y + bounds.height / 2 - r.y - r.height / 2;
+		node.translate(dx, dy);
+		revalidate(); // Otherwise, this branch will not layout
+
+		// Pass the location to all children
+		for (int i = 0; i < subtrees.size(); i++) {
+			TreeBranch subtree = (TreeBranch) subtrees.get(i);
+			subtree.setBounds(bounds);
+			subtree.animationReset(bounds);
+		}
+	}
+	
+	
+	private void collapseLocation(Rectangle bounds) {
+		List subtrees = contents.getChildren();
+		for ( int i = 0; i < subtrees.size(); i++ ) {
+			TreeBranch subtree = (TreeBranch) subtrees.get(i);
+			subtree.invalidate();
+			subtree.setBounds(bounds);
+			revalidate();
+		}
+	}
+
+
+	public void collapse() {
+		if (!expanded)
+			return;
+		fireExpanded(false);
+		IFigure root = this;
+		Viewport port = null;
+		Point viewportStart = null;
+		while (root.getParent() != null) {
+			if (root instanceof Viewport)
+				port = ((Viewport) root);
+			root = root.getParent();
+		}
+		viewportStart = port.getViewLocation();
+
+		Animation.markBegin();
+		
+		LayoutManager layout1 = contents.getLayoutManager();
+		contents.setLayoutManager(new FreeformLayout());
+		contents.invalidate();
+		collapseLocation(getNodeBounds());
+		
+		Animation.run(ANIMATION_TIME);
+		port.setViewLocation(viewportStart);
+		contents.setLayoutManager(layout1);
+		setExpanded(false);
+	}
+
+	/**
+	 * @see org.eclipse.draw2d.Figure#containsPoint(int, int)
+	 */
+	public boolean containsPoint(int x, int y) {
+		return node.containsPoint(x, y) || contents.containsPoint(x, y);
+	}
+
+	public void expand() {
+		if (expanded)
+			return;
+		fireExpanded(true);
+		Animation.markBegin();
+		animationReset(getNodeBounds());
+		setExpanded(true);
+		Animation.run(ANIMATION_TIME);
+	}
+
+	public int getAlignment() {
+		return aligment;
+	}
+
+	protected BranchLayout getBranchLayout() {
+		return (BranchLayout) getLayoutManager();
+	}
+
+	public IFigure getContentsPane() {
+		return contents;
+	}
+
+	public int[] getContourLeft() {
+		return getBranchLayout().getContourLeft();
+	}
+
+	public int[] getContourRight() {
+		return getBranchLayout().getContourRight();
+	}
+
+	public int getDepth() {
+		return getBranchLayout().getDepth();
+	}
+
+	/**
+	 * @see org.eclipse.draw2d.Figure#getMinimumSize(int, int)
+	 */
+	public Dimension getMinimumSize(int wHint, int hHint) {
+		
+		//if (!AnimationoldAnimation)
+			validate();
+		return super.getMinimumSize(wHint, hHint);
+	}
+
+	public PageNode getNode() {
+		return node;
+	}
+
+	public Rectangle getNodeBounds() {
+		return node.getBounds();
+	}
+
+	public int[] getPreferredRowHeights() {
+		return getBranchLayout().getPreferredRowHeights();
+	}
+
+	/**
+	 * @see org.eclipse.draw2d.Figure#getPreferredSize(int, int)
+	 */
+	public Dimension getPreferredSize(int wHint, int hHint) {
+		//if (!AnimationoldAnimation)
+			validate();
+		return super.getPreferredSize(wHint, hHint);
+	}
+
+	public TreeRoot getRoot() {
+		return ((TreeBranch) getParent().getParent()).getRoot();
+	}
+
+	public int getStyle() {
+		return style;
+	}
+
+	/**
+	 * @return
+	 */
+	public boolean isExpanded() {
+		return expanded;
+	}
+	
+	protected boolean hasChildren() {
+		return (contents.getChildren().size() > 0);
+	}
+
+	/**
+	 * @see org.eclipse.draw2d.Figure#paintFigure(org.eclipse.draw2d.Graphics)
+	 */
+	protected void paintFigure(Graphics graphics) {
+		super.paintFigure(graphics);
+		node.setHasChildren(this.hasChildren());
+		if (isExpanded())
+			getBranchLayout().paintLines(graphics);
+		// if (getDepth() == 2)
+		// graphics.drawRectangle(getBounds().getResized(-1, -1));
+	}
+
+	public void setAlignment(int value) {
+		aligment = value;
+		revalidate();
+	}
+	
+	/**
+	 * @param b
+	 */
+	public void setExpanded(boolean b) {
+		if (expanded == b)
+			return;
+		expanded = b;
+		contents.setVisible(b);
+		node.setExpanded(b);
+		revalidate();
+	}
+
+	public void setNode(IFigure node) {
+		remove(this.node);
+		add(this.node, 0);
+	}
+
+	public void setRowHeights(int heights[], int offset) {
+		getBranchLayout().setRowHeights(heights, offset);
+	}
+
+	public void setStyle(int style) {
+		if (this.style == style)
+			return;
+		this.style = style;
+		switch (style) {
+		case STYLE_HANGING:
+			setLayoutManager(new HangingLayout(this));
+			node.setHangingLayoutStyle(true);
+			contents.setLayoutManager(new ToolbarLayout(false));
+			break;
+
+		default:
+			setLayoutManager(new NormalLayout(this));
+			node.setHangingLayoutStyle(false);
+			contents.setLayoutManager(new TreeLayout());
+			break;
+		}
+	}
+
+	/**
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		return toString(0);
+	}
+	
+	public void addExpandListener(ExpandListener listener) {
+		Iterator iterator = expandListeners.iterator();
+		while ( iterator.hasNext() ) {
+			ExpandListener listener2 =(ExpandListener) iterator.next();
+			if ( listener2 == listener ) {
+				iterator.remove();
+			}
+		}
+		expandListeners.add(listener);
+	}
+	
+	public void removeExpandListener(ExpandListener listener) {
+		Iterator iterator = expandListeners.iterator();
+		while ( iterator.hasNext() ) {
+			ExpandListener listener2 =(ExpandListener) iterator.next();
+			if ( listener2 == listener ) {
+				iterator.remove();
+			}
+		}
+	}
+	
+	private void fireExpanded( boolean expanded ) {
+		Iterator iterator = expandListeners.iterator();
+		while ( iterator.hasNext() ) {
+			ExpandListener listener =(ExpandListener) iterator.next();
+			if ( expanded )
+				listener.expand(this);
+			else
+				listener.collapse(this);
+		}
+	}
+
+	public String toString(int level) {
+		String result = "";
+		for (int i = 0; i < level; i++)
+			result += "  ";
+		result += getChildren().get(1) + "\n";
+		for (int i = 0; i < contents.getChildren().size(); i++)
+			result += ((TreeBranch) contents.getChildren().get(i)).toString(level + 1);
+		return result;
+	}
+
+	/**
+	 * @see org.eclipse.draw2d.Figure#validate()
+	 */
+	public void validate() {
+		if (isValid())
+			return;
+//		/*
+//		if (style == STYLE_HANGING) {
+//			ToolbarLayout layout = new ToolbarLayout(!getRoot().isHorizontal()) {
+//				public void layout(IFigure parent) {
+//					//Animation.markBegin();
+//					/*
+//					oldAnimation.recordInitialState(parent);
+//					if (oldAnimation.playbackState(parent))
+//						return;
+//						*/
+//
+//					super.layout(parent);
+//					//Animation.run(200);
+//				}
+//
+//			};
+//			layout.setMinorAlignment(ToolbarLayout.ALIGN_TOPLEFT);
+//			layout.setStretchMinorAxis(false);
+//			contents.setLayoutManager(layout);
+//		}
+		
+		repaint();
+		super.validate();
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeGraphViewerImpl.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeGraphViewerImpl.java
new file mode 100644
index 0000000..bbf6d95
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeGraphViewerImpl.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.FlowLayout;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.LayoutAnimator;
+import org.eclipse.draw2d.MouseEvent;
+import org.eclipse.draw2d.MouseListener;
+import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+
+
+/**
+ * This was originally a Draw2D Snippet that has been modified for Zest. All bugs 
+ * in this should be opened against the Zest project.
+ * 
+ * @author hudsonr Created on Apr 22, 2003
+ * @author Ian Bull
+ */
+public class TreeGraphViewerImpl extends Canvas {
+	
+	FigureCanvas figureCanvas = null;
+	IFigure contents = null;
+	boolean animate = true;
+	TreeRoot root;
+	PageNode selected;
+	boolean treeCompression = false;
+	boolean hangingStyle = false;
+
+
+	public TreeGraphViewerImpl(Composite parent, int style) {
+		super(parent, style);
+		
+		if ( (style & ZestStyles.TREE_GRAPH_COMPRESS) > 0 ) {
+			// @tag style(tree_graph(compress))
+			treeCompression = true;
+		}
+		if ( (style & ZestStyles.TREE_GRAPH_HANGING_LAYOUT ) > 0 ) {
+			// @tag style(tree_graph(hanging))
+			hangingStyle = true;
+		}
+		this.setLayout(new FillLayout());
+		figureCanvas = new FigureCanvas(this);
+		figureCanvas.setLayout(new FillLayout());	
+	}
+	
+	private FigureCanvas getFigureCanvas() {
+		return figureCanvas;
+	}
+
+
+	PageNode createPageNode(String title) {
+		final PageNode node = new PageNode(title);
+		node.addMouseListener(new MouseListener.Stub() {
+			public void mousePressed(MouseEvent me) {
+				setSelected(node);
+			}
+
+			public void mouseDoubleClicked(MouseEvent me) {
+				doExpandCollapse();
+			}
+		});
+		return node;
+	}
+
+	void doAddChild() {
+		if (selected == null)
+			return;
+		TreeBranch parent = (TreeBranch) selected.getParent();
+		parent.getContentsPane().add(new TreeBranch(createPageNode("child"), parent.getStyle()));
+	}
+
+	void doAlignCenter() {
+		if (selected == null)
+			return;
+		TreeBranch parent = (TreeBranch) selected.getParent();
+		parent.setAlignment(PositionConstants.CENTER);
+	}
+
+	void doAlignLeft() {
+		if (selected == null)
+			return;
+		TreeBranch parent = (TreeBranch) selected.getParent();
+		parent.setAlignment(PositionConstants.LEFT);
+	}
+
+	void doDeleteChild() {
+		if (selected == null)
+			return;
+		TreeBranch parent = (TreeBranch) selected.getParent();
+		IFigure contents = parent.getContentsPane();
+		if (contents.getChildren().isEmpty())
+			return;
+		contents.remove((IFigure) contents.getChildren().get(contents.getChildren().size() - 1));
+	}
+
+	void doExpandCollapse() {
+		if (selected == null)
+			return;
+		TreeBranch parent = (TreeBranch) selected.getParent();
+		if (parent.getContentsPane().getChildren().isEmpty())
+			return;
+		if (animate) {
+			
+			if (parent.isExpanded())
+				parent.collapse();
+			else
+				parent.expand();
+				
+		} else
+			parent.setExpanded(!parent.isExpanded());
+	}
+
+	void doStyleHanging() {
+		if (selected == null)
+			return;
+		TreeBranch parent = (TreeBranch) selected.getParent();
+		parent.setStyle(TreeBranch.STYLE_HANGING);
+	}
+
+	void doStyleNormal() {
+		if (selected == null)
+			return;
+		TreeBranch parent = (TreeBranch) selected.getParent();
+		parent.setStyle(TreeBranch.STYLE_NORMAL);
+	}
+
+	
+	
+	/**
+	 * @see org.eclipse.draw2d.examples.AbstractExample#getContents()
+	 */
+	public void setContents(Object input, ITreeContentProvider contentProvider, ILabelProvider labelProvider) {
+		
+		getFigureCanvas().setBackground(ColorConstants.white);
+		IFigure f = new Figure();
+		
+		FlowLayout flowLayout = new FlowLayout(false);
+		f.addLayoutListener(LayoutAnimator.getDefault());
+		flowLayout.setMinorAlignment(FlowLayout.ALIGN_LEFTTOP);
+		
+		f.setLayoutManager(flowLayout);
+		TreeGraphViewerModelFactory factory = new TreeGraphViewerModelFactory(this, contentProvider, labelProvider);
+		TreeRoot[] roots = factory.createModel(contentProvider.getElements(input));
+		for (int i = 0; i < roots.length; i++) {
+			f.add( roots[i] );
+			// @tag style(tree_graph) : Sets the compression on the tree
+			roots[i].setCompression(treeCompression);
+		}
+		getFigureCanvas().setContents(f);
+		this.contents = f;
+	}
+
+	
+
+	void setSelected(PageNode node) {
+		if (selected != null) {
+			selected.setSelected(false);
+		}
+		selected = node;
+		selected.setSelected(true);
+	}
+
+	public boolean getHangingStyle() {
+		// @tag style(tree_graph(hanging))
+		return hangingStyle;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeGraphViewerModelFactory.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeGraphViewerModelFactory.java
new file mode 100644
index 0000000..07cec11
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeGraphViewerModelFactory.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright 2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import org.eclipse.draw2d.MouseEvent;
+import org.eclipse.draw2d.MouseListener;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+
+/**
+ * This was originally a Draw2D Snippet that has been modified for Zest. All bugs 
+ * in this should be opened against the Zest project.
+ * 
+ * @author hudsonr Created on Apr 22, 2003
+ * @author Ian Bull
+ */
+public class TreeGraphViewerModelFactory {
+	
+	ILabelProvider labelProvider = null;
+	TreeGraphViewerImpl viewerImpl = null;
+	ITreeContentProvider treeContentProvider = null;
+	
+	public TreeGraphViewerModelFactory(TreeGraphViewerImpl viewerImpl,	
+			ITreeContentProvider treeContentProvider,
+			ILabelProvider labelProvider) {
+		
+		this.treeContentProvider = treeContentProvider;
+		this.viewerImpl = viewerImpl;
+		this.labelProvider = labelProvider;
+	}
+	
+	public TreeRoot[] createModel(Object[] elements) {
+		if ( elements == null ) return new TreeRoot[0];
+		
+		TreeRoot[] roots = new TreeRoot[elements.length];
+		for (int i = 0; i < elements.length; i++) {
+			roots[i] = createRoot(elements[i]);
+			createChildren(roots[i], elements[i]);
+		}
+		return roots;
+	}
+	
+	private void createChildren(TreeBranch parent, Object element) {
+		Object[] children = treeContentProvider.getChildren(element);
+		if ( children == null ) return;
+		for (int i = 0; i < children.length; i++) {
+			Object currentChild = children[i];
+			TreeBranch childBranch = createBranch(parent, currentChild);
+			createChildren(childBranch, currentChild);
+		}
+	}
+	
+	private TreeRoot createRoot(Object o) {
+		String label = labelProvider.getText(o);
+		int hangingStyle = viewerImpl.getHangingStyle() ? TreeBranch.STYLE_HANGING : TreeBranch.STYLE_NORMAL;
+		TreeRoot root = new TreeRoot(createPageNode(label), hangingStyle);
+		return root;
+	}
+	
+	private TreeBranch createBranch(TreeBranch parent, Object o) {
+		String label = labelProvider.getText(o);
+		int hangingStyle = viewerImpl.getHangingStyle() ? TreeBranch.STYLE_HANGING : TreeBranch.STYLE_NORMAL;
+		TreeBranch branch = new TreeBranch(createPageNode(label), hangingStyle);
+		parent.getContentsPane().add(branch);
+		// @tag hack : I should not expand and then collapse the nodes
+		parent.setExpanded(true);
+		parent.setExpanded(false);
+		return branch;
+	}
+	
+	
+	private PageNode createPageNode(String title) {
+		final PageNode node = new PageNode(title);
+		node.addMouseListener(new MouseListener.Stub() {
+			public void mousePressed(MouseEvent me) {
+				viewerImpl.setSelected(node);
+			}
+
+			public void mouseDoubleClicked(MouseEvent me) {
+				viewerImpl.doExpandCollapse();
+			}
+		});
+		return node;
+	}
+	
+	
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeLayout.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeLayout.java
new file mode 100644
index 0000000..a866886
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeLayout.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import java.util.List;
+
+import org.eclipse.draw2d.AbstractLayout;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.draw2d.geometry.Transposer;
+
+/**
+ * Performs a layout on a container containing {@link AbstractBranch} figures.
+ * This layout is similar to FlowLayout, except that the children are squeezed
+ * together to overlap by comparing their left and right contours.
+ * 
+ * This was originally a Draw2D Snippet that has been modified for Zest. All bugs 
+ * in this should be opened against the Zest project.
+ * @author hudsonr Created on Apr 22, 2003
+ * @author Ian Bull
+ */
+public class TreeLayout extends AbstractLayout {
+
+	private int pointOfContact;
+
+	/**
+	 * @see org.eclipse.draw2d.AbstractLayout#calculatePreferredSize(org.eclipse.draw2d.IFigure,
+	 *      int, int)
+	 */
+	protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint) {
+		container.validate();
+		List children = container.getChildren();
+		Rectangle result = new Rectangle().setLocation(container.getClientArea().getLocation());
+		for (int i = 0; i < children.size(); i++)
+			result.union(((IFigure) children.get(i)).getBounds());
+		result.resize(container.getInsets().getWidth(), container.getInsets().getHeight());
+		return result.getSize();
+	}
+
+	private int[] calculateNewRightContour(int old[], int add[], int shift) {
+		if (old == null)
+			return add;
+		// if (shift < 0)
+		// shift = 0;
+		int result[] = new int[Math.max(old.length, add.length)];
+	
+		for ( int i = 0; i < add.length; i++ ) {
+			result[i] = add[i];
+		}
+		for (int i = add.length; i < result.length; i++)
+			result[i] = old[i] + shift;
+		return result;
+	}
+
+	private int calculateOverlap(int leftSubtree[], int rightSubtree[]) {
+		pointOfContact = 0;
+		if (leftSubtree == null)
+			return 0;
+		int min = Math.min(leftSubtree.length, rightSubtree.length);
+		int result = Integer.MAX_VALUE;
+		for (int i = 0; i < min; i++) {
+			int current = leftSubtree[i] + rightSubtree[i];
+			if (i > 0)
+				current -= 5;
+			if (current < result) {
+				result = current;
+				pointOfContact = i + 1;
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * @see org.eclipse.draw2d.LayoutManager#layout(org.eclipse.draw2d.IFigure)
+	 */
+	public void layout(IFigure container) {
+		/*
+		Animation.markBegin();
+		if (LayoutAnimator.getDefault()..playbackState(container))
+			return;
+			*/
+		
+		TreeRoot root = ((TreeBranch) container.getParent()).getRoot();
+		Transposer transposer = root.getTransposer();
+		int gap = root.getMinorSpacing();
+		List subtrees = container.getChildren();
+		TreeBranch subtree;
+		int previousSubtreeDepth = 0;
+		int rightContour[] = null;
+		int leftContour[];
+		int contactDepth;
+
+		Point reference = transposer.t(container.getBounds().getLocation());
+		Point currentXY = reference.getCopy();
+
+		for (int i = 0; i < subtrees.size(); i++) {
+			subtree = (TreeBranch) subtrees.get(i);
+
+			// Give the subtree its preferred size before asking for contours
+			Dimension subtreeSize = subtree.getPreferredSize();
+			subtree.setSize(subtreeSize);
+			subtreeSize = transposer.t(subtreeSize);
+
+			leftContour = subtree.getContourLeft();
+			int overlap = calculateOverlap(rightContour, leftContour);
+			if (!subtree.getRoot().isCompressed())
+				overlap = 0;
+			contactDepth = pointOfContact;
+			subtree.setLocation(transposer.t(currentXY.getTranslated(-overlap, 0)));
+
+			// Setup value for next sibling
+			int advance = gap + subtreeSize.width - overlap;
+			rightContour = calculateNewRightContour(rightContour, subtree.getContourRight(), advance);
+			currentXY.x += advance;
+
+			/*
+			 * In some cases, the current child may extend beyond the left edge
+			 * of the container because of the way it overlaps with the previous
+			 * child. When this happens, shift all children right.
+			 */
+			int shiftRight = reference.x - transposer.t(subtree.getBounds()).x;
+			if (shiftRight > 0) {
+				currentXY.x += shiftRight;
+				Point correction = transposer.t(new Point(shiftRight, 0));
+				for (int j = 0; j <= i; j++)
+					((IFigure) subtrees.get(j)).translate(correction.x, correction.y);
+			}
+
+			/*
+			 * In some cases, the current child "i" only touches the contour of
+			 * a distant sibling "i-n", where n>1. This means that there is
+			 * extra space that can be distributed among the intermediate
+			 * siblings
+			 */
+
+			if (contactDepth > previousSubtreeDepth) {
+				TreeBranch branch = (TreeBranch) subtrees.get(i - 1);
+				int slack = transposer.t(subtree.getBounds()).x - transposer.t(branch.getBounds()).right() - gap
+						+ calculateOverlap(branch.getContourRight(), subtree.getContourLeft());
+				int end = i;
+				int begin = end - 1;
+				while (begin > 0 && ((TreeBranch) subtrees.get(begin)).getDepth() < contactDepth)
+					begin--;
+
+				for (int j = begin + 1; j < end; j++) {
+					branch = (TreeBranch) subtrees.get(j);
+					Point shift = transposer.t(new Point(slack * (j - begin) / (end - begin), 0));
+					branch.translate(shift.x, shift.y);
+				}
+			}
+			previousSubtreeDepth = subtree.getDepth();
+		}
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeRoot.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeRoot.java
new file mode 100644
index 0000000..9ccd957
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeRoot.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import org.eclipse.draw2d.LayoutAnimator;
+import org.eclipse.draw2d.geometry.Transposer;
+
+/**
+ * This was originally a Draw2D Snippet that has been modified for Zest. All bugs 
+ * in this should be opened against the Zest project.
+ * 
+ * @author hudsonr Created on Apr 23, 2003
+ * @author Ian Bull
+ */
+public class TreeRoot extends TreeBranch {
+
+	private int major = 10;
+	private int minor = 10;
+	private Transposer transposer = new Transposer();
+
+	private boolean compression;
+
+	public TreeRoot( String text ) {
+		this(new PageNode(text));
+	}
+	
+	/**
+	 * @param title
+	 */
+	public TreeRoot(PageNode title) {
+		super(title);
+		this.addLayoutListener(LayoutAnimator.getDefault());
+	}
+
+	/**
+	 * @param title
+	 * @param style
+	 */
+	public TreeRoot(PageNode title, int style) {
+		super(title, style);
+	}
+
+	public int getMajorSpacing() {
+		return major;
+	}
+
+	/**
+	 * @return
+	 */
+	public int getMinorSpacing() {
+		return minor;
+	}
+
+	public TreeRoot getRoot() {
+		return this;
+	}
+
+	public Transposer getTransposer() {
+		return transposer;
+	}
+
+	public boolean isHorizontal() {
+		return !transposer.isEnabled();
+	}
+
+	/**
+	 * sets the space (in pixels) between this branch's node and its subtrees.
+	 */
+	public void setMajorSpacing(int value) {
+		this.major = value;
+		invalidateTree();
+		revalidate();
+	}
+
+	public void setHorizontal(boolean value) {
+		transposer.setEnabled(!value);
+		invalidateTree();
+		revalidate();
+	}
+
+	/**
+	 * @param i
+	 */
+	public void setMinorSpacing(int i) {
+		minor = i;
+		invalidateTree();
+		revalidate();
+	}
+
+	/**
+	 * @see org.eclipse.draw2d.Figure#validate()
+	 */
+	public void validate() {
+		if (isValid())
+			return;
+		setRowHeights(getPreferredRowHeights(), 0);
+		super.validate();
+	}
+
+	/**
+	 * @return
+	 */
+	public boolean isCompressed() {
+		return compression;
+	}
+
+	/**
+	 * @param b
+	 */
+	public void setCompression(boolean b) {
+		compression = b;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeStyle.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeStyle.java
new file mode 100644
index 0000000..1bf55b8
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/treegraphviewer/TreeStyle.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright 2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.treegraphviewer;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Toggle;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.mylar.zest.core.IZestImageConstants;
+import org.eclipse.mylar.zest.core.ZestPlugin;
+
+/**
+ * 
+ * @author Ian Bull
+ */
+public class TreeStyle extends Toggle {
+	{
+		setPreferredSize(12, 12);
+	}
+
+	private PageNode node = null;
+
+	public TreeStyle(PageNode node) {
+		this.node = node;
+	}
+
+	/**
+	 * @see org.eclipse.draw2d.Figure#paintFigure(org.eclipse.draw2d.Graphics)
+	 */
+	protected void paintFigure(Graphics g) {
+		super.paintFigure(g);
+
+		g.setBackgroundColor(ColorConstants.black);
+		g.setForegroundColor(ColorConstants.black);
+		
+		Rectangle r = Rectangle.SINGLETON;
+		r.setBounds(getBounds()).resize(-1, -1);
+
+		// If the node is selected use the inverse icons
+		// because they look much better
+		
+		if (node.isSelected()) {
+			if (isSelected())
+				g.drawImage(ZestPlugin.getDefault().getImageRegistry().get(IZestImageConstants.TREE_HANGING_INVERSE_ICON), r.x,	r.y);
+			else
+				g.drawImage(ZestPlugin.getDefault().getImageRegistry().get(IZestImageConstants.TREE_NORMAL_INVERSE_ICON), r.x, r.y);
+		} else {
+			if (isSelected())
+				g.drawImage(ZestPlugin.getDefault().getImageRegistry().get(IZestImageConstants.TREE_HANGING_ICON), r.x, r.y);
+			else
+				g.drawImage(ZestPlugin.getDefault().getImageRegistry().get(IZestImageConstants.TREE_NORMAL_ICON), r.x, r.y);
+		}
+		
+		
+
+	}
+
+	protected boolean useLocalCoordinates() {
+		return true;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/NoOverlapLayout.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/NoOverlapLayout.java
new file mode 100644
index 0000000..664db29
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/NoOverlapLayout.java
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Iterator;
+
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.EditPart;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphviewer.parts.GraphNodeEditPart;
+
+
+/**
+ * The NoOverlapLayout class will check all sibling nodes to ensure that the given
+ * bounds don't overlap.   
+ * 
+ * @author Chris Callendar
+ */
+public class NoOverlapLayout  {
+
+	public static final int DEFAULT_SPACING = 30;
+	
+	private int spacing;
+	
+	/**
+	 * Initializes the layout with the default spacing.
+	 */
+	public NoOverlapLayout() {
+		this(DEFAULT_SPACING);
+	}
+	
+	/**
+	 * Initializes the layout with the given spacing.
+	 * @param spacing the spacing between figures (positive #).
+	 */
+	public NoOverlapLayout(int spacing) {
+		this.spacing = (spacing <= 0 ? DEFAULT_SPACING : spacing);
+	}
+	
+	/**
+	 * Applies the no overlap layout algorithm.  The bounds Rectangle
+	 * <b>will</b> be modified if overlapping occurs.
+	 * All the sibling nodes' bounds will <b>not</b> be checked for overlapping, only the
+	 * given bounds will be checked against the existing nodes' bounds.
+	 * When overlapping occurs the nodes are layed out beside, above, or below.  This 
+	 * position will be the closest position in which no overlapping occurs.
+	 * @param bounds the bounds to check
+	 * @return Rectangle the same Rectangle adjusted if necessary (returned for convenience)
+	 */
+	public Rectangle checkBounds(GraphNodeEditPart editPart, Rectangle bounds) {
+		ArrayList rectangles = new ArrayList(editPart.getParent().getChildren().size());
+		for (Iterator iter = editPart.getParent().getChildren().iterator(); iter.hasNext(); ) {
+			EditPart part = (EditPart)iter.next();
+			if (part instanceof GraphNodeEditPart) {
+				GraphNodeEditPart graphEditPart = (GraphNodeEditPart)part;
+				if (graphEditPart != editPart) {
+					IGraphModelNode node = (IGraphModelNode)editPart.getModel();
+					Rectangle rect = new Rectangle(node.getLocation(), node.getSize());
+					rectangles.add(rect);
+				}
+			}
+		}
+		// now check if this bounds overlaps and adjust if necessary
+		addRectangle(rectangles, bounds);
+		return bounds;
+	}
+	
+	/**
+	 * Checks if the rectangle overlaps with any existing Rectangle in the list.  
+	 * If it does then the bounds are adjusted to try and ensure no overlap.
+	 * @param rectangles A list of Rectangle objects 
+	 * @param bounds the rectangle to check
+	 * @return Rectangle the same Rectangle, adjusted in location if necessary
+	 */
+	public Rectangle addRectangle(ArrayList rectangles, Rectangle bounds) {
+		for (int i = 0; i < rectangles.size(); i++) {
+			Object obj = rectangles.get(i);
+			if (obj instanceof Rectangle) {
+				Rectangle rect = (Rectangle)obj;
+				Rectangle intersect = rect.getIntersection(bounds);
+				if (!intersect.isEmpty()) {
+					//boolean onleft = (bounds.x < rect.x);
+					//boolean onup = (bounds.y < rect.y);
+					int xleft = rect.x - bounds.width - spacing;
+					int xright = rect.x + rect.width + spacing;
+					int yup = rect.y - bounds.height - spacing;
+					int ydown = rect.y + rect.height + spacing;
+					
+					Point ref = intersect.getCenter();
+					Point xl = new Point(xleft, bounds.y);
+					Point xr = new Point(xright, bounds.y);
+					Point yu = new Point(bounds.x, yup);
+					Point yd = new Point(bounds.x, ydown);
+					Point left = new Point(xleft, rect.y);
+					Point right = new Point(xright, rect.y);
+					Point above = new Point(rect.x, yup);
+					Point below = new Point(rect.x, ydown);
+					Point[] sortedPoints = sortPoints(ref, new Point[] { xl, left, xr, right, yu, above, yd, below });
+					for (int j = 0; j < sortedPoints.length; j++) {
+						bounds.setLocation(sortedPoints[j]);
+						boolean ok = true;
+						for (int k = 0; k < i; k++) {
+							Rectangle r = (Rectangle)rectangles.get(k);
+							if (!r.getIntersection(bounds).isEmpty()) {
+								ok = false;
+								break;
+							}
+						}
+						if (ok) {
+							break;
+						}
+						// set it back to the first point since it is the smallest movement
+						if (j == (sortedPoints.length - 1)) {
+							bounds.setLocation(sortedPoints[0]);
+						}
+					}
+				}
+			}				
+		}
+		rectangles.add(bounds);
+		return bounds;
+	}
+	
+	/**
+	 * Sorts the points putting the points closest to the reference
+	 * point first.  A new array is returned.
+	 * @param ref	 The reference point.
+	 * @param points The points to sort.
+	 * @return Point[] the same Points array for convenience
+	 */
+	private Point[] sortPoints(Point ref, Point[] points) {
+		Arrays.sort(points, new PointComparator(ref, true));
+		return points;
+	}
+
+		
+	/**
+	 * A class for comparing {@link Point} objects to a reference Point.
+	 * 
+	 * @author Chris Callendar
+	 */
+	class PointComparator implements Comparator {
+
+		private Point ref;
+		private boolean preferPositivePoints;
+
+		/**
+		 * Initializes this comparator with the given reference point.
+		 * Positive points get preference over points containing negative values.
+		 * @param ref the reference point to compare all points to.
+		 */
+		public PointComparator(Point ref) {
+			this(ref, true);
+		}
+
+		/**
+		 * Initializes this comparator with the given reference point.
+		 * @param ref the reference point to compare all points to.
+		 * @param preferPositivePoints if points whose (x,y) values are positive are preferred.
+		 */
+		public PointComparator(Point ref, boolean preferPositivePoints) {
+			this.ref = ref;
+			this.preferPositivePoints = preferPositivePoints;
+		}
+		
+		/**
+		 * Compares two Points and returns -1 if the first Point is 
+		 * closer to the reference point than the second.
+		 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+		 */
+		public int compare(Object obj1, Object obj2) {
+			int rv = 0;
+			if ((obj1 instanceof Point) && (obj2 instanceof Point)) {
+				Point p1 = (Point)obj1;
+				Point p2 = (Point)obj2;
+				int dist1 = ref.getDistance2(p1);
+				int dist2 = ref.getDistance2(p2);
+
+				// if preferPositivePoints is true, then give preference
+				// to positive points.  If both are positive or both are negative 
+				// then go with the closest point
+				boolean p1pos = ((p1.x >= 0) && (p1.y >= 0));
+				boolean p2pos = ((p2.x >= 0) && (p2.y >= 0));
+				if (preferPositivePoints && (p1pos && p2pos)) {
+					rv = (dist1 - dist2);
+				} else if (p1pos) {
+					rv = -1;
+				} else if (p2pos) {
+					rv = 1;
+				} else {
+					rv = (dist1 - dist2);
+				}
+			}
+			return rv;
+		}
+		
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/NoOverlapLayoutAlgorithm.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/NoOverlapLayoutAlgorithm.java
new file mode 100644
index 0000000..47afb8f
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/NoOverlapLayoutAlgorithm.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.layouts.NestedLayoutEntity;
+
+
+/**
+ * A simple layout algorithm that attempts to properly size a 
+ * list of nodes as well as any children under those nodes.
+ * 
+ * @author Chris Callendar
+ */
+public class NoOverlapLayoutAlgorithm {
+
+	private NoOverlapLayout noOverlapLayout;
+	
+	/**
+	 * Initializes this algorithm.
+	 */
+	public NoOverlapLayoutAlgorithm() {
+		this.noOverlapLayout = new NoOverlapLayout();
+	}
+	
+	/**
+	 * Recursively lays out the nodes and their children.  Starts with the nodes that
+	 * have no children and then traverses up the parent hierarchy laying out each node 
+	 * based on the size of its children.
+	 * The nodes should not overlap.
+	 * @param rootNodes
+	 */
+	public void layout(List rootNodes) {
+		if (rootNodes != null) {
+
+			ArrayList boundsList = new ArrayList(rootNodes.size());
+			for (Iterator iter = rootNodes.iterator(); iter.hasNext(); ) {
+				IGraphModelNode node = (IGraphModelNode)iter.next();
+				Dimension dim = node.calculateMinimumLabelSize();
+				node.setSizeInLayout(dim.width, dim.height);
+				
+				if (node instanceof NestedLayoutEntity) {
+					// layout the children
+					layout(((NestedLayoutEntity)node).getChildren());
+				}
+				
+				Dimension childSize = node.calculateMinimumSize();
+				Rectangle rect = new Rectangle(node.getLocation(), childSize);
+				
+				noOverlapLayout.addRectangle(boundsList, rect);
+
+				// ensure that the new position is inside the bounds
+				// TODO causes overlapping, so not very useful
+//				if (enforeBounds && (bounds != null) && !bounds.isEmpty()) {
+//					if (rect.right() > bounds.right()) {
+//						rect.x = bounds.right() - rect.width;
+//					}
+//					if (rect.bottom() > bounds.bottom()) {
+//						rect.y = bounds.bottom() - rect.height;
+//					}
+//					if (rect.x < bounds.x) {
+//						rect.x = bounds.x;
+//					}
+//					if (rect.y < bounds.y) {
+//						rect.y = bounds.y;
+//					}
+//				}
+				
+				node.setLocationInLayout(rect.x, rect.y);
+				node.setSizeInLayout(rect.width, rect.height);
+			}
+
+		}
+		
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/commands/NoResizeNodeConstraintCommand.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/commands/NoResizeNodeConstraintCommand.java
new file mode 100644
index 0000000..b929679
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/commands/NoResizeNodeConstraintCommand.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.commands;
+
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.RequestConstants;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+
+
+/**
+ * Supports moving of GraphModelNode objects (no resizing).
+ * 
+ * @author Chris Callendar
+ */
+public class NoResizeNodeConstraintCommand extends Command {
+
+	/** Stores the old size and location. */
+	//private Rectangle oldBounds;
+	
+	/** A request to move/resize an edit part. */
+	private final ChangeBoundsRequest request;
+	
+	/**
+	 * GraphSetConstraintCommand constructor.
+	 */
+	public NoResizeNodeConstraintCommand(IGraphModelNode node, ChangeBoundsRequest request, Rectangle newBounds) {
+		if (node == null || request == null || newBounds == null) {
+			throw new IllegalArgumentException("Couldn't create a GraphSetConstraint with those parameters");
+		}
+		this.request = request;
+		this.setLabel("Move");
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.commands.Command#canExecute()
+	 */
+	public boolean canExecute() {
+		Object type = request.getType();
+		// make sure the Request is of a type we support:
+
+		return (RequestConstants.REQ_MOVE.equals(type) || RequestConstants.REQ_MOVE_CHILDREN.equals(type));
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.commands.Command#execute()
+	 */
+	public void execute() {
+//		oldBounds = new Rectangle(node.getLocation(), node.getSize());
+//		redo();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.commands.Command#redo()
+	 */
+	public void redo() {
+//		node.setLocationInLayout(newBounds.x, newBounds.y);
+//		node.setSizeInLayout(newBounds.width, newBounds.height);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.commands.Command#undo()
+	 */
+	public void undo() {
+//		node.setLocationInLayout(oldBounds.x, oldBounds.y);
+//		node.setSizeInLayout(oldBounds.width, oldBounds.height);
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/commands/PanningCommand.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/commands/PanningCommand.java
new file mode 100644
index 0000000..ce1a331
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/commands/PanningCommand.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.commands;
+
+import org.eclipse.gef.commands.Command;
+
+
+/**
+ * A command for panning.  Does nothing, but canExecute() returns true.
+ * 
+ * @author Chris Callendar
+ */
+public class PanningCommand extends Command {
+
+	/**
+	 * PanningCommand constructor. 
+	 */
+	public PanningCommand() {
+		super();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.commands.Command#canExecute()
+	 */
+	public boolean canExecute() {
+		return true;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.commands.Command#execute()
+	 */
+	public void execute() {
+
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/commands/ResizeNodeConstraintCommand.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/commands/ResizeNodeConstraintCommand.java
new file mode 100644
index 0000000..0b743ad
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/commands/ResizeNodeConstraintCommand.java
@@ -0,0 +1,156 @@
+/***********************************************************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada. All rights reserved. This program and the
+ * accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors: The Chisel Group, University of Victoria
+ **********************************************************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.commands;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.RequestConstants;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.gef.requests.ChangeBoundsRequest;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts.NestedGraphNodeEditPart;
+
+/**
+ * A command to resize and/or move a node. The command can be undone or redone.
+ * 
+ * @author Chris Callendar
+ */
+public class ResizeNodeConstraintCommand extends Command {
+
+	/** Stores the new size and location. */
+	private final Rectangle newBounds;
+
+	/** Stores the old size and location. */
+	private Rectangle oldBounds;
+
+	/** A request to move/resize an edit part. */
+	private final ChangeBoundsRequest request;
+
+	/** Node to manipulate. */
+	private final IGraphModelNode node;
+
+	/** The Edit part of the node */
+	private final NestedGraphNodeEditPart editPart;
+
+	private boolean enforceBounds;
+
+	/**
+	 * Create a command that can resize and/or move a node.
+	 * 
+	 * @param node
+	 *            the node to mode/resize
+	 * @param req
+	 *            the move and resize request
+	 * @param newBounds
+	 *            the new size and location
+	 * @throws IllegalArgumentException
+	 *             if any of the parameters is null
+	 */
+	public ResizeNodeConstraintCommand(NestedGraphNodeEditPart editPart, IGraphModelNode node, ChangeBoundsRequest req,
+			Rectangle newBounds) {
+		if (node == null || req == null || newBounds == null) {
+			throw new IllegalArgumentException();
+		}
+		this.editPart = editPart;
+		this.node = node;
+		this.request = req;
+		this.newBounds = newBounds.getCopy();
+		this.enforceBounds = false;
+		setLabel("Move / Resize");
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.gef.commands.Command#canExecute()
+	 */
+	public boolean canExecute() {
+		Object type = request.getType();
+		if ( RequestConstants.REQ_RESIZE_CHILDREN.equals(type) || RequestConstants.REQ_MOVE_CHILDREN.equals(type)) {
+			IFigure parentFigure = editPart.getFigure().getParent();
+			
+			Rectangle  parentBounds = parentFigure.getBounds().getCopy();
+			// @tag zest(bug(152289)) : Enforce bounds for resize in Nested Viewer
+			// If the new bounds are outside the parent return false
+			
+			Rectangle myBounds = newBounds.getCopy();
+			parentFigure.translateToParent(myBounds);
+			if ( myBounds.x < parentBounds.x ||
+				myBounds.y < parentBounds.y ||
+				myBounds.width > ( parentBounds.width - myBounds.x) ||
+				myBounds.height > ( parentBounds.height - myBounds.y )) return false;
+			return true;
+		}
+		// make sure the Request is of a type we support:
+		return (RequestConstants.REQ_MOVE.equals(type) || RequestConstants.REQ_MOVE_CHILDREN.equals(type)
+				|| RequestConstants.REQ_RESIZE.equals(type) || RequestConstants.REQ_RESIZE_CHILDREN.equals(type));
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.gef.commands.Command#execute()
+	 */
+	public void execute() {
+		oldBounds = new Rectangle(node.getLocation(), node.getSize());
+		redo();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.gef.commands.Command#redo()
+	 */
+	public void redo() {
+
+		node.setSizeInLayout(newBounds.getSize().width, newBounds.getSize().height);
+		if (enforceBounds && false) {
+			Rectangle rect = ((NestedGraphNodeEditPart)editPart.getParent()).getAbsoluteBounds();
+			if ((newBounds.right() > rect.width)) {
+				newBounds.x = rect.width - newBounds.width;
+			}
+			if ((newBounds.bottom() > rect.height)) {
+				newBounds.y = rect.height - newBounds.height;
+			}
+			newBounds.x = Math.max(0, newBounds.x);
+			newBounds.y = Math.max(0, newBounds.y);
+		}
+
+		// check if the new bounds overlaps any of the existing nodes
+
+		// move the current editpart's figure to last in the list to put it on
+		// top
+		IFigure fig = editPart.getFigure();
+		fig.getParent().getChildren().remove(fig);
+		fig.getParent().getChildren().add(fig);
+
+		node.setLocation(newBounds.getLocation().x, newBounds.getLocation().y);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.gef.commands.Command#undo()
+	 */
+	public void undo() {
+		node.setSizeInLayout(oldBounds.getSize().width, oldBounds.getSize().height);
+		node.setLocation(oldBounds.getLocation().x, oldBounds.getLocation().y);
+	}
+
+
+	/**
+	 * Sets if the bounds are enforced. If a node is moved outside the bounds it
+	 * will be placed at the boundary.
+	 * 
+	 * @param enforceBounds
+	 */
+	public void setEnforceBounds(boolean enforceBounds) {
+		this.enforceBounds = enforceBounds;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/AspectRatioFreeformLayer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/AspectRatioFreeformLayer.java
new file mode 100644
index 0000000..5ec7092
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/AspectRatioFreeformLayer.java
@@ -0,0 +1,250 @@
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+import org.eclipse.draw2d.FreeformLayer;
+import org.eclipse.draw2d.FreeformLayout;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.MarginBorder;
+import org.eclipse.draw2d.ScalableFigure;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.PrecisionDimension;
+import org.eclipse.draw2d.geometry.PrecisionPoint;
+import org.eclipse.draw2d.geometry.PrecisionRectangle;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.draw2d.geometry.Translatable;
+import org.eclipse.draw2d.text.CaretInfo;
+import org.eclipse.mylar.zest.core.internal.gefx.XYScaledGraphics;
+
+//@tag zest.bug.156286-Scaling.fix : make this implement scalable figure so that a zoom manager can be used on GraphEditParts.
+public class AspectRatioFreeformLayer extends FreeformLayer implements ScalableFigure {
+	
+	
+
+
+
+	private double widthScale = 1.0;
+	private double heigthScale = 1.0;
+
+	
+	public AspectRatioFreeformLayer(String debugLabel ) {
+		widthScale = 1D;
+		heigthScale = 1D;
+		setLayoutManager(new FreeformLayout());
+		setBorder(new MarginBorder(5));
+		
+		
+		//setOpaque(false);
+	}
+	
+
+	
+	public void setScale( double wScale, double hScale ) {
+		this.widthScale = wScale;
+		this.heigthScale = hScale;
+	}
+		
+	public double getWidthScale() {
+		return this.widthScale;
+	}
+	
+	public double getHeightScale() {
+		return this.heigthScale;
+	}
+	
+	
+	public boolean isCoordinateSystem() {
+		// TODO Auto-generated method stub
+		return true;
+	}
+	
+	public double getScale() {
+		// TODO Auto-generated method stub
+		throw new RuntimeException("Operation not supported");
+		// return this.widthScale;
+		
+		//throw new RuntimeException("Operation Not supported");
+	}
+	
+	public void setScale(double scale) {
+		//super.setScale( scale );
+		this.widthScale = scale;
+		this.heigthScale = scale;
+		revalidate();
+		repaint();
+		//System.out.println("Operation not supported");
+		//throw new RuntimeException("Operation not supported");
+	}
+	
+	
+	
+	
+	/**
+	 * @see org.eclipse.draw2d.Figure#getClientArea()
+	 */
+
+	public Rectangle getClientArea(Rectangle rect) {
+		//return super.getClientArea(rect);
+		
+		rect.width /= widthScale;
+		rect.height /= heigthScale;
+		return rect;
+	}
+
+	
+
+	public Dimension getPreferredSize(int wHint, int hHint) {
+		Dimension d = super.getPreferredSize(wHint, hHint);
+		int w = getInsets().getWidth();
+		int h = getInsets().getHeight();
+		return d.getExpanded(-w, -h).scale(widthScale, heigthScale).expand(w,h);
+	}
+
+
+	public void translateFromParent(Translatable t) {
+		super.translateFromParent(t);
+		//t.performScale(1/widthScale);
+		
+		
+		if ( t instanceof PrecisionRectangle ) {
+			PrecisionRectangle r = (PrecisionRectangle)t;
+			r.preciseX *= 1/widthScale;
+			r.preciseY *= 1/heigthScale;
+			r.preciseWidth *= 1/widthScale;
+			r.preciseHeight *= 1/heigthScale;
+			r.updateInts();
+		}
+		else if ( t instanceof Rectangle ) {
+			Rectangle r = (Rectangle)t;
+			r.scale(1/widthScale, 1/heigthScale);
+		}
+		else if ( t instanceof CaretInfo ) {
+			CaretInfo c = (CaretInfo)t;
+			c.performScale(1/heigthScale);
+		}
+		else if ( t instanceof PrecisionDimension ) {
+			PrecisionDimension d = (PrecisionDimension)t;
+			d.preciseWidth *= 1/widthScale;
+			d.preciseHeight *= 1/heigthScale;
+			d.updateInts();
+		}
+		else if ( t instanceof Dimension ) {
+			Dimension d = (Dimension) t;
+			d.scale(1/widthScale, 1/heigthScale);
+		}
+		else if ( t instanceof PrecisionPoint ) {
+			PrecisionPoint p = (PrecisionPoint) t;
+			p.preciseX *= 1/widthScale;
+			p.preciseY *= 1/heigthScale;
+			p.updateInts();
+		}
+		else if ( t instanceof Point ) {
+			Point p = (Point)t;
+			p.scale(1/widthScale, 1/heigthScale);
+		}
+		else if ( t instanceof PointList ) {
+			throw new RuntimeException("PointList not supported in AspectRatioScale");
+		}
+		else {
+			throw new RuntimeException( t.toString() + " not supported in AspectRatioScale");
+		}
+		
+		
+		//t.performScale(1/widthScale);		
+	}
+	
+
+	public void translateToParent(Translatable t) {
+		//t.performScale(widthScale);
+		
+		if ( t instanceof PrecisionRectangle ) {
+			PrecisionRectangle r = (PrecisionRectangle)t;
+			r.preciseX *= widthScale;
+			r.preciseY *= heigthScale;
+			r.preciseWidth *= widthScale;
+			r.preciseHeight *= heigthScale;
+			r.updateInts();
+		}
+		else if ( t instanceof Rectangle ) {
+			Rectangle r = (Rectangle)t;
+			//r.performScale(widthScale);
+			r.scale(widthScale, heigthScale);
+		}
+		else if ( t instanceof CaretInfo ) {
+			CaretInfo c = (CaretInfo)t;
+			c.performScale(heigthScale);
+		}
+		else if ( t instanceof PrecisionDimension ) {
+			PrecisionDimension d = (PrecisionDimension)t;
+			d.preciseWidth *= widthScale;
+			d.preciseHeight *= heigthScale;
+			d.updateInts();
+		}
+		else if ( t instanceof Dimension ) {
+			Dimension d = (Dimension) t;
+			d.scale(widthScale, heigthScale);
+		}
+		else if ( t instanceof PrecisionPoint ) {
+			PrecisionPoint p = (PrecisionPoint) t;
+			p.preciseX *= widthScale;
+			p.preciseY *= heigthScale;
+			p.updateInts();
+		}
+		else if ( t instanceof Point ) {
+			Point p = (Point)t;
+			p.scale(widthScale, heigthScale);
+		}
+		else if ( t instanceof PointList ) {
+			throw new RuntimeException("PointList not supported in AspectRatioScale");
+		}
+		else {
+			throw new RuntimeException( t.toString() + " not supported in AspectRatioScale");
+		}
+		
+		
+		super.translateToParent(t);
+	}
+
+
+	//protected boolean useLocalCoordinates() {
+	//	return true;
+	//}
+
+	
+	protected void paintClientArea(Graphics graphics) {
+		
+		if (getChildren().isEmpty())
+			return;
+
+		XYScaledGraphics g = null;
+		boolean disposeGraphics = false;
+		if (graphics instanceof XYScaledGraphics) {
+			g = (XYScaledGraphics)graphics;
+		} else {
+			g = new XYScaledGraphics(graphics);
+			disposeGraphics = true;
+		}
+
+		boolean optimizeClip = getBorder() == null || getBorder().isOpaque();
+		if (!optimizeClip) {
+			g.clipRect(getBounds().getCropped(getInsets()));
+		}
+		
+		//g.translate((int)(getBounds().x + getInsets().left) , 
+		//		(int)(getBounds().y  +  getInsets().top) );
+		
+		g.scale(widthScale, heigthScale	);
+		//g.scale(widthScale);
+		
+		//g.scale(widthScale);
+		g.pushState();
+		paintChildren(g);
+		g.popState();
+		if (disposeGraphics) {
+			g.dispose();
+			graphics.restoreState();
+		}
+		
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/AspectRatioScaledFigure.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/AspectRatioScaledFigure.java
new file mode 100644
index 0000000..567e392
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/AspectRatioScaledFigure.java
@@ -0,0 +1,292 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+
+
+import java.util.List;
+
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.FreeformLayout;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.TreeSearch;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.PrecisionDimension;
+import org.eclipse.draw2d.geometry.PrecisionPoint;
+import org.eclipse.draw2d.geometry.PrecisionRectangle;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.draw2d.geometry.Translatable;
+import org.eclipse.draw2d.text.CaretInfo;
+import org.eclipse.mylar.zest.core.internal.gefx.XYScaledGraphics;
+
+
+/**
+ * 
+ * @author irbull
+ *
+ */
+public class AspectRatioScaledFigure extends Figure {// extends ScaledFigure {
+	
+	private double widthScale = 1.0;
+	private double heigthScale = 1.0;
+	
+	public AspectRatioScaledFigure(String debugLabel ) {
+		widthScale = 1D;
+		heigthScale = 1D;
+		setLayoutManager(new FreeformLayout());
+		setOpaque(true);
+	}
+	
+	public void setSize(int w, int h) {
+		// TODO Auto-generated method stub
+		super.setSize(w, h);
+		
+	}
+	
+	
+	public void setScale( double wScale, double hScale ) {
+		this.widthScale = wScale;
+		this.heigthScale = hScale;
+	}
+	
+	public double getWidthScale() {
+		return this.widthScale;
+	}
+	
+	public double getHeightScale() {
+		return this.heigthScale;
+	}
+	
+	
+	public boolean isCoordinateSystem() {
+		// TODO Auto-generated method stub
+		return true;
+	}
+	
+	public double getScale() {
+		// TODO Auto-generated method stub
+		throw new RuntimeException("Operation not supported");
+		// return this.widthScale;
+		
+		//throw new RuntimeException("Operation Not supported");
+	}
+	
+	public void setScale(double scale) {
+		//super.setScale( scale );
+		this.widthScale = scale;
+		this.heigthScale = scale;
+		revalidate();
+		repaint();
+		//System.out.println("Operation not supported");
+		//throw new RuntimeException("Operation not supported");
+	}
+	
+	
+	
+	
+	/**
+	 * @see org.eclipse.draw2d.Figure#getClientArea()
+	 */
+	
+	public Rectangle getClientArea(Rectangle rect) {
+		super.getClientArea(rect);
+		
+		rect.width /= widthScale;
+		rect.height /= heigthScale;
+		return rect;
+	}
+	
+	public Dimension getPreferredSize(int wHint, int hHint) {
+		Dimension d = super.getPreferredSize(wHint, hHint);
+		int w = getInsets().getWidth();
+		int h = getInsets().getHeight();
+		return d.getExpanded(-w, -h).scale(widthScale, heigthScale).expand(w,h);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#translateFromParent(org.eclipse.draw2d.geometry.Translatable)
+	 */
+	public void translateFromParent(Translatable t) {
+		super.translateFromParent(t);
+		//t.performScale(1/widthScale);
+		
+		
+		if ( t instanceof PrecisionRectangle ) {
+			PrecisionRectangle r = (PrecisionRectangle)t;
+			r.preciseX *= 1/widthScale;
+			r.preciseY *= 1/heigthScale;
+			r.preciseWidth *= 1/widthScale;
+			r.preciseHeight *= 1/heigthScale;
+			r.updateInts();
+		}
+		else if ( t instanceof Rectangle ) {
+			Rectangle r = (Rectangle)t;
+			r.scale(1/widthScale, 1/heigthScale);
+		}
+		else if ( t instanceof CaretInfo ) {
+			CaretInfo c = (CaretInfo)t;
+			c.performScale(1/heigthScale);
+		}
+		else if ( t instanceof PrecisionDimension ) {
+			PrecisionDimension d = (PrecisionDimension)t;
+			d.preciseWidth *= 1/widthScale;
+			d.preciseHeight *= 1/heigthScale;
+			d.updateInts();
+		}
+		else if ( t instanceof Dimension ) {
+			Dimension d = (Dimension) t;
+			d.scale(1/widthScale, 1/heigthScale);
+		}
+		else if ( t instanceof PrecisionPoint ) {
+			PrecisionPoint p = (PrecisionPoint) t;
+			p.preciseX *= 1/widthScale;
+			p.preciseY *= 1/heigthScale;
+			p.updateInts();
+		}
+		else if ( t instanceof Point ) {
+			Point p = (Point)t;
+			p.scale(1/widthScale, 1/heigthScale);
+		}
+		else if ( t instanceof PointList ) {
+			throw new RuntimeException("PointList not supported in AspectRatioScale");
+		}
+		else {
+			throw new RuntimeException( t.toString() + " not supported in AspectRatioScale");
+		}
+		
+		//t.performScale(1/widthScale);		
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#findFigureAt(int, int, org.eclipse.draw2d.TreeSearch)
+	 */
+	public IFigure findFigureAt(int x, int y, TreeSearch search) {
+		// TODO Auto-generated method stub\
+		IFigure f = super.findFigureAt(x, y, search);
+		//System.out.println("Figure: " + f + " at " + x + " : " + y);
+		return f;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#translateToParent(org.eclipse.draw2d.geometry.Translatable)
+	 */
+	public void translateToParent(Translatable t) {
+
+		//t.performScale(widthScale);
+		
+		if ( t instanceof PrecisionRectangle ) {
+			PrecisionRectangle r = (PrecisionRectangle)t;
+			r.preciseX *= widthScale;
+			r.preciseY *= heigthScale;
+			r.preciseWidth *= widthScale;
+			r.preciseHeight *= heigthScale;
+			r.updateInts();
+		}
+		else if ( t instanceof Rectangle ) {
+			Rectangle r = (Rectangle)t;
+			//r.performScale(widthScale);
+			r.scale(widthScale, heigthScale);
+		}
+		else if ( t instanceof CaretInfo ) {
+			CaretInfo c = (CaretInfo)t;
+			c.performScale(heigthScale);
+		}
+		else if ( t instanceof PrecisionDimension ) {
+			PrecisionDimension d = (PrecisionDimension)t;
+			d.preciseWidth *= widthScale;
+			d.preciseHeight *= heigthScale;
+			d.updateInts();
+		}
+		else if ( t instanceof Dimension ) {
+			Dimension d = (Dimension) t;
+			d.scale(widthScale, heigthScale);
+		}
+		else if ( t instanceof PrecisionPoint ) {
+			PrecisionPoint p = (PrecisionPoint) t;
+			p.preciseX *= widthScale;
+			p.preciseY *= heigthScale;
+			p.updateInts();
+		}
+		else if ( t instanceof Point ) {
+			Point p = (Point)t;
+			p.scale(widthScale, heigthScale);
+		}
+		else if ( t instanceof PointList ) {
+			throw new RuntimeException("PointList not supported in AspectRatioScale");
+		}
+		else {
+			throw new RuntimeException( t.toString() + " not supported in AspectRatioScale");
+		}
+		
+		
+		super.translateToParent(t);
+		
+	}
+
+	
+	protected boolean useLocalCoordinates() {
+		return true;
+	}
+	
+	protected void paintClientArea(Graphics graphics) {
+		if (getChildren().isEmpty())
+			return;
+
+		XYScaledGraphics g = null;
+		boolean disposeGraphics = false;
+		if (graphics instanceof XYScaledGraphics) {
+			g = (XYScaledGraphics)graphics;
+		} else {
+			g = new XYScaledGraphics(graphics);
+			disposeGraphics = true;
+		}
+
+		
+		boolean optimizeClip = getBorder() == null || getBorder().isOpaque();
+		if (!optimizeClip) {
+			g.clipRect(getBounds().getCropped(getInsets()));
+		}
+		
+		g.translate((int)(getBounds().x + getInsets().left) , 
+				(int)(getBounds().y  +  getInsets().top) );
+		
+		g.scale(widthScale, heigthScale	);
+		//g.scale(widthScale);
+		
+		//g.scale(widthScale);
+		g.pushState();
+		paintChildren(g);
+		g.popState();
+		if (disposeGraphics) {
+			g.dispose();
+			graphics.restoreState();
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#paintChildren(org.eclipse.draw2d.Graphics)
+	 */
+	protected void paintChildren(Graphics graphics) {
+		IFigure child;
+		List children = getChildren();
+		Rectangle clip = Rectangle.SINGLETON;
+		for (int i = 0; i < children.size(); i++) {
+			child = (IFigure)children.get(i);
+			if (child.isVisible() && child.intersects(graphics.getClip(clip))) {
+				graphics.clipRect(child.getBounds());
+				child.paint(graphics);
+				graphics.restoreState();
+			}
+		}
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/CompartmentFigure.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/CompartmentFigure.java
new file mode 100644
index 0000000..a5b9da3
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/CompartmentFigure.java
@@ -0,0 +1,65 @@
+/***********************************************************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada. All rights reserved. This program and the
+ * accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors: The Chisel Group, University of Victoria
+ **********************************************************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+import org.eclipse.draw2d.AbstractBorder;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.ToolbarLayout;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Insets;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+/**
+ * A simple Figure that holds other figures.
+ * 
+ * @author Chris Callendar
+ */
+public class CompartmentFigure extends Figure {
+
+	private ToolbarLayout layout = null;
+	private Dimension minSize = null;
+	
+	public CompartmentFigure() {
+		this.layout = new ToolbarLayout();
+		this.minSize = new Dimension(0, 0);
+
+		layout.setVertical(true);
+		layout.setMinorAlignment(ToolbarLayout.ALIGN_TOPLEFT);
+		layout.setStretchMinorAxis(true);
+		layout.setSpacing(4);
+		setLayoutManager(layout);
+		setBorder(new CompartmentFigureBorder());
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#add(org.eclipse.draw2d.IFigure, java.lang.Object, int)
+	 */
+	public void add(IFigure figure, Object constraint, int index) {
+		super.add(figure, constraint, index);
+		if (constraint instanceof Rectangle) {
+			Rectangle rect = (Rectangle) constraint;
+			minSize.expand(Math.max(0, (rect.width - minSize.width)), rect.height);
+			setMinimumSize(minSize);
+		}
+	}
+	
+	public class CompartmentFigureBorder extends AbstractBorder {
+
+		public Insets getInsets(IFigure figure) {
+			return new Insets(4);
+		}
+
+		public void paint(IFigure figure, Graphics graphics, Insets insets) {
+			graphics.drawLine(getPaintRectangle(figure, insets).getTopLeft(), tempRect.getTopRight());
+		}
+
+	}
+	
+}
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/EdgeBorder.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/EdgeBorder.java
new file mode 100644
index 0000000..85f283d
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/EdgeBorder.java
@@ -0,0 +1,199 @@
+/***********************************************************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada. All rights reserved. This program and the
+ * accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this
+ * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors: The Chisel Group, University of Victoria
+ **********************************************************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.LineBorder;
+import org.eclipse.draw2d.geometry.Insets;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.swt.graphics.Color;
+
+/**
+ * An extension of the LineBorder class
+ * to allow for setting the color and width of each edge of the bounding rectangle.
+ * 
+ * @author Chris Callendar
+ */
+public class EdgeBorder extends LineBorder {
+	
+	/** The edge widths: top, left, bottom, right. */
+	private int[] widths = new int[] { 1, 1, 1, 1};
+	
+	/** The edge colors: top, left, bottom, right. */
+	private Color[] colors = new Color[4];
+
+	/**
+	 * Initializes this border to be like a LineBorder - one color and one width.
+	 * @param color
+	 * @param allsides
+	 */
+	public EdgeBorder(Color color, int allsides) {
+		super();
+		setColor(color);
+		setWidth(allsides);
+	}
+	
+	/**
+	 * Initializes this border with all sides have the one color, and each side
+	 * having a specific width.
+	 */
+	public EdgeBorder(Color color, int top, int left, int bottom, int right) {
+		super();
+		setColor(color);
+		setWidths(top, left, bottom, right);
+	}
+	
+	/**
+	 * Sets the colors and widths for the border.<br>
+	 * Array of length 1: all sides get the same values.
+	 * Array of length 2: {top/bottom, left/right}
+	 * Array of length 4: {top, left, bottom, right}
+	 * @param colors array of colors: must be length 1, 2, or 4
+	 * @param widths array of widths: must be length 1, 2, or 4
+	 * @throws IllegalArgumentException if the two arrays 
+	 */
+	public EdgeBorder(Color[] colors, int[] widths) {
+		super();
+		setColors(colors);
+		setWidths(widths);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.LineBorder#paint(org.eclipse.draw2d.IFigure, org.eclipse.draw2d.Graphics, org.eclipse.draw2d.geometry.Insets)
+	 */
+	public void paint(IFigure figure, Graphics graphics, Insets insets) {
+		tempRect.setBounds(getPaintRectangle(figure, insets));
+		int x1 = tempRect.x,
+			x2 = tempRect.x + tempRect.width,
+			y1 = tempRect.y,
+			y2 = tempRect.y + tempRect.height;
+		
+		// top
+		paintLine(graphics, widths[0], colors[0], new Point(x1, y1), new Point(x2-widths[0], y1));
+		// left
+		paintLine(graphics, widths[1], colors[1], new Point(x1, y1), new Point(x1, y2-widths[1]));
+		// bottom
+		paintLine(graphics, widths[2], colors[2], new Point(x1, y2-widths[2]), new Point(x2-widths[2], y2-widths[2]));
+		// right
+		paintLine(graphics, widths[3], colors[3], new Point(x2-widths[3], y1), new Point(x2-widths[3], y2-widths[3]));
+	}
+		
+	public void paintLine(Graphics g, int width, Color color, Point p1, Point p2) {
+		if (width > 0) {
+			g.setLineWidth(width);
+			g.setForegroundColor(color);
+			g.drawLine(p1, p2);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.LineBorder#setWidth(int)
+	 */
+	public void setWidth(int allsides) {
+		super.setWidth(allsides);
+		setWidths(allsides, allsides, allsides, allsides);
+	}
+	
+	/**
+	 * Sets the width for the edges.  The array must be of 
+	 * length 1 (all sides get the same width), 2 (top/bottom and 
+	 * left/right get same width), or 4.
+	 * @param widths the widths: must be length 1, 2, or 4
+	 */
+	public void setWidths(int[] widths) {
+		if (widths.length == 1) {
+			setWidth(widths[0]);
+		} else if (widths.length == 2) {
+			setWidths(widths[0], widths[1], widths[0], widths[1]);
+		} else if (widths.length == 4) {
+			setWidths(widths[0], widths[1], widths[2], widths[3]);
+		}
+	}
+	
+	/**
+	 * Sets the widths of the border's edges.
+	 * @param top
+	 * @param left
+	 * @param bottom
+	 * @param right
+	 */
+	public void setWidths(int top, int left, int bottom, int right) {
+		super.setWidth(top);
+		this.widths[0] = top;
+		this.widths[1] = left;
+		this.widths[2] = bottom;
+		this.widths[3] = right;		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.LineBorder#setColor(org.eclipse.swt.graphics.Color)
+	 */
+	public void setColor(Color color) {
+		super.setColor(color);
+		setColors(color, color, color, color);
+	}
+	
+	/**
+	 * Sets the colors for the edges.  The array must be of length
+	 * 1 (all sides same color), 2 (top/bottom and left/right same colors) or 4.
+	 * @param colors the colors array, must be of length 1, 2, 4
+	 */
+	public void setColors(Color[] colors) {
+		if (colors.length == 1) {
+			setColor(colors[0]);
+		} else if (colors.length == 2) {
+			setColors(colors[0], colors[1], colors[0], colors[1]);
+		} else if (colors.length == 4) {
+			setColors(colors[0], colors[1], colors[2], colors[3]);
+		}
+	}
+	
+	/**
+	 * Sets the colors of the border's edges.
+	 * @param topColor
+	 * @param leftColor
+	 * @param bottomColor
+	 * @param rightColor
+	 */
+	public void setColors(Color topColor, Color leftColor, Color bottomColor, Color rightColor) {
+		super.setColor(topColor);
+		this.colors[0] = topColor;
+		this.colors[1] = leftColor;
+		this.colors[2] = bottomColor;
+		this.colors[3] = rightColor;
+	}
+	
+	/**
+	 * Returns the color of the border.  If multiple edge colors are defined (for each edge)
+	 * then this is just the top edge color.
+	 * @see org.eclipse.draw2d.LineBorder#getColor()
+	 */
+	public Color getColor() {
+		return colors[0];
+	}
+
+	/**
+	 * Returns the width of the border.  If multiple edge widths are defined
+	 * then this is just the top edge width.
+	 * @see org.eclipse.draw2d.LineBorder#getWidth()
+	 */
+	public int getWidth() {
+		return widths[0];
+	}
+
+	/** 
+	 * Returns the insets.
+	 * @return Inserts
+	 */
+	public Insets getInsets(IFigure figure) {
+		Insets insets = new Insets(widths[0], widths[1], widths[2], widths[3]);
+		return insets;
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/Graph.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/Graph.java
new file mode 100644
index 0000000..4ead0b3
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/Graph.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+
+
+/**
+ * The Graph class is a FigureCanvas used for displaying graph items 
+ * such as nodes and edges.  Scrollbars are not shown by default.
+ * 
+ * @author Chris Callendar
+ */
+public class Graph extends Canvas {
+
+	/**
+	 * @param parent
+	 */
+	public Graph(Composite parent) {
+		super(parent, SWT.NONE);
+		
+		//setScrollBarVisibility(FigureCanvas.NEVER);
+	}
+
+	
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/GraphLabel.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/GraphLabel.java
new file mode 100644
index 0000000..068d754
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/GraphLabel.java
@@ -0,0 +1,204 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.FigureUtilities;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.MarginBorder;
+import org.eclipse.draw2d.StackLayout;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.mylar.zest.core.internal.gefx.CachedLabel;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Overrides the Draw2D Label Figure class to ensure that the text is never truncated.
+ * Also draws a rounded rectangle border.
+ * 
+ * @author Chris Callendar
+ */
+public class GraphLabel extends CachedLabel {
+		
+	private Color borderColor;
+	private int borderWidth;
+	private int arcWidth;
+
+	private boolean painting = false;
+
+	/**
+	 * Creates a GraphLabel 
+	 * @param cacheLabel Determine if the text should be cached.  This will make it faster, but the 
+	 * text is not as clear
+	 */
+	public GraphLabel(boolean cacheLabel) {
+		this("", cacheLabel);
+	}
+	
+	/**
+	 * Creates a graph label with text
+	 * @param text The text
+	 * @param cacheLabel Determine if the text should be cached.  This will make it faster, but the
+	 */
+	public GraphLabel(String text, boolean cacheLabel) {
+		this("", null, cacheLabel);
+	}
+	
+	/**
+	 * Creates the graph label with an image
+	 * @param i The Image
+	 * @param cacheLabel Determine if the text should be cached.  This will make it faster, but the
+	 */
+	public GraphLabel(Image i, boolean cacheLabel) {
+		this("", i, cacheLabel);
+	}
+	
+	/**
+	 * Creates a graph label with an image and text
+	 * @param text The text
+	 * @param i The Image
+	 * @param cacheLabel Determine if the text should be cached.  This will make it faster, but the
+	 */
+	public GraphLabel(String text, Image i, boolean cacheLabel) {
+		super(cacheLabel);
+		initLabel();
+		setText(text);
+		setIcon(i);
+	}
+	
+	/**
+	 * Initializes the border color, border width, and sets the layout manager.
+	 * Also sets the font to be the default system font.
+	 */
+	protected void initLabel() {
+		super.setFont(Display.getDefault().getSystemFont());
+		this.borderColor = ColorConstants.black;
+		this.borderWidth = 1;
+		this.arcWidth = 8;
+		this.setLayoutManager(new StackLayout());
+		this.setBorder(new MarginBorder(1));
+	}
+	
+	public void setOpaque(boolean opaque) {
+		// TODO Auto-generated method stub
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#setFont(org.eclipse.swt.graphics.Font)
+	 */
+	public void setFont(Font f) {
+		super.setFont(f);
+		adjustBoundsToFit();
+	}
+	
+	/**
+	 * Adjust the bounds to make the text fit without truncation.
+	 */
+	protected void adjustBoundsToFit() {
+		String text = getText();
+		if ((text != null) && (text.length() > 0)) {
+			Font font = getFont();
+			if (font != null) {
+				Dimension minSize = FigureUtilities.getTextExtents(text, font);
+				if (getIcon() != null) {
+					org.eclipse.swt.graphics.Rectangle imageRect = getIcon().getBounds();
+					int expandHeight = Math.max(imageRect.height - minSize.height, 0);
+					minSize.expand(imageRect.width + 4, expandHeight);
+				}
+				minSize.expand(10 + (2*borderWidth), 4 + (2*borderWidth));
+				setBounds(new Rectangle(getLocation(), minSize));
+			}
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Label#paintFigure(org.eclipse.draw2d.Graphics)
+	 */           
+	public void paint(Graphics graphics) {
+		
+		graphics.setForegroundColor(getForegroundColor());
+		graphics.setBackgroundColor(getBackgroundColor());
+		
+		// fill in the background
+		Rectangle bounds = getBounds().getCopy();
+		graphics.fillRoundRectangle(bounds, arcWidth, arcWidth);
+		
+		super.paint(graphics);
+		// paint the border
+		graphics.setForegroundColor(getBorderColor());
+		graphics.setLineWidth(getBorderWidth());
+		bounds.setSize(bounds.width-1, bounds.height-1);
+		graphics.drawRoundRectangle(bounds, arcWidth, arcWidth);
+	}
+	
+	protected Color getBackgroundTextColor() {
+		return getBackgroundColor();
+	}
+	
+	/**
+	 * This method is overridden to ensure that it doesn't get called while
+	 * the super.paintFigure() is being called.  Otherwise NullPointerExceptions
+	 * can occur because the icon or text locations are cleared *after* they were calculated.
+	 * 
+	 * @see org.eclipse.draw2d.Label#invalidate()
+	 */
+	public void invalidate() {
+		if (!painting) {
+			super.invalidate();
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Label#setText(java.lang.String)
+	 */
+	public void setText(String s) {
+		super.setText(s);
+		adjustBoundsToFit();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Label#setIcon(org.eclipse.swt.graphics.Image)
+	 */
+	public void setIcon(Image image) {
+		super.setIcon(image);
+		adjustBoundsToFit();
+	}
+	
+	public Color getBorderColor() {
+		return borderColor;
+	}
+	
+	public void setBorderColor(Color c) {
+		this.borderColor = c;
+	}
+	
+	public int getBorderWidth() {
+		return borderWidth;
+	}
+	
+	public void setBorderWidth(int width) {
+		this.borderWidth = width;
+	}
+
+	
+	public int getArcWidth() {
+		return arcWidth;
+	}
+
+	public void setArcWidth(int arcWidth) {
+		this.arcWidth = arcWidth;
+	}
+
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/MinMaxFigure.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/MinMaxFigure.java
new file mode 100644
index 0000000..2fefabe
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/MinMaxFigure.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+import org.eclipse.draw2d.ButtonModel;
+import org.eclipse.draw2d.ChangeEvent;
+import org.eclipse.draw2d.ChangeListener;
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Label;
+import org.eclipse.draw2d.Toggle;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.mylar.zest.core.messages.ZestUIMessages;
+
+/**
+ * A simple figure that displays an icon for minimizing/maximizing panels.
+ * @author Del Myers
+ *
+ */
+
+//@tag bug(152613-Client-Supplier(fix)) : this figure allows the client and supplier pains have a method for users to minimize/maximize them.
+public class MinMaxFigure extends Toggle {
+	Label toolTip;
+		
+	/**
+	 * 
+	 */
+	public MinMaxFigure() {
+		super();
+		setForegroundColor(ColorConstants.black);
+		setBackgroundColor(ColorConstants.white);
+		setPreferredSize(14,14);
+		toolTip = new Label(ZestUIMessages.TIP_MINIMIZE);
+		setToolTip(toolTip);
+		add(toolTip);
+		getModel().addChangeListener(new ChangeListener(){
+			public void handleStateChanged(ChangeEvent event) {
+				if (ButtonModel.SELECTED_PROPERTY.equals(event.getPropertyName())) {
+					updateToolTip();
+			}
+		}});
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#setValid(boolean)
+	 */
+	public void setValid(boolean value) {
+		super.setValid(value);
+		repaint();
+	}
+	
+	protected void paintFigure(Graphics graphics) {
+		super.paintFigure(graphics);
+		Rectangle bounds = getBounds().getCopy();
+		bounds.width = bounds.width - 3;
+		bounds.height = bounds.height - 4;
+		bounds.x = bounds.x+1;
+		bounds.y = bounds.y+1;
+		if (isSelected()) {
+			graphics.fillRectangle(bounds);
+			graphics.drawRectangle(bounds);
+		}
+		Rectangle bar = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height/4);
+		graphics.fillRectangle(bar);
+		graphics.drawRectangle(bar);
+	}
+	
+		
+	/**
+	 * @return true if image for maximization should be drawn.
+	 */
+	public boolean isMax() {
+		return isSelected();
+	}
+	
+	/**
+	 * @param max true if the image for maximizing should be drawn.
+	 */
+	public void setMax(boolean max) {
+		if (max == isMax()) return;
+		setSelected(max);
+		
+	}
+	
+	/**
+	 * Updates the tooltip to match the current state.
+	 */
+	private void updateToolTip() {
+		boolean max = isMax();
+		if (!max) {
+			toolTip.setText(ZestUIMessages.TIP_MINIMIZE);
+		} else {
+			toolTip.setText(ZestUIMessages.TIP_MAXIMIZE);
+		}
+		toolTip.repaint();
+
+	}
+
+}
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/NestedFigure.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/NestedFigure.java
new file mode 100644
index 0000000..6287d70
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/NestedFigure.java
@@ -0,0 +1,347 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+import org.eclipse.draw2d.Clickable;
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.FigureUtilities;
+import org.eclipse.draw2d.FreeformLayout;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Label;
+import org.eclipse.draw2d.LineBorder;
+import org.eclipse.draw2d.PositionConstants;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Insets;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * A simple Figure which has a title and a CompartmentFigure which holds
+ * other nested figures.
+ * 
+ * @author Chris Callendar
+ */
+public class NestedFigure extends Figure {
+
+	private Label label = null;
+	
+	//private Clickable button = null;[irbull]
+	
+	/** Container figure for other figures */
+	private AspectRatioScaledFigure scaledFigure = null;
+	
+	
+	/**
+	 * Initializes this nested figure without a Clickable figure and no ScrollPane.
+	 * @param label	The label to display at the top of the nested figure
+	 */
+	public NestedFigure(Label label) {
+		this(label, null, false);
+	}
+	
+	/**
+	 * Initializes this nested figure and possibly adds a Clickable figure
+	 * in the top left corner.  The ScaledFigure is not put inside a ScrollPane.
+	 * @param label	The label to display at the top of the nested figure
+	 * @param button A Clickable figure which is put in the top left corner
+	 */
+	public NestedFigure(Label label, Clickable button) {
+		this(label, button, false);
+	}
+	
+	
+	/**
+	 * Returns true if the given point is in the label, false otherwise
+	 * @param p The point to test
+	 * @return True if the given point is in the label, false otherwise
+	 */
+	public boolean isPointInLabel( Point p ) {
+		return label.containsPoint(p);
+	}
+
+	public Insets getInsets() {
+		// TODO Auto-generated method stub
+		return new Insets(0,0,0,0);
+	}
+	
+	/**
+	 * Creates a nested figure possibly with a plus/minus figure.
+	 * @param label	The label to display at the top of the nested figure
+	 * @param button A Clickable figure which is put in the top left corner
+	 * @param addScrollPane If the ScaledFigure should be contained inside a ScrollPane
+	 */
+	public NestedFigure(Label label, Clickable button, boolean addScrollPane) {
+		super();
+		this.label = label;
+		this.label.setOpaque(true);
+		this.label.setLabelAlignment(PositionConstants.CENTER);
+
+		this.scaledFigure = new AspectRatioScaledFigure(label.getText());
+		
+		this.scaledFigure.setVisible(false);
+		
+		this.scaledFigure.setOpaque(true);
+		
+		
+		FreeformLayout layout = new FreeformLayout();
+		
+		setLayoutManager(layout);
+		setBorder(new LineBorder(ColorConstants.black, 1));
+		setOpaque(true);
+		scaledFigure.setBackgroundColor(ColorConstants.white);
+		
+		
+		add(label, new Rectangle(0, 0, -1, -1), 0);
+		if (button != null) {
+			add(button, new Rectangle(0, 0, -1, -1));
+		}
+		
+		add(scaledFigure, new Rectangle(0, 18, -1, -1));
+		
+	}
+	
+	protected Dimension calculateLabelSize() {
+		String text = label.getText();
+		Dimension minSize = new Dimension(0, 0);
+		/*[irbull]
+		if (button != null) {
+			minSize.expand(button.getPreferredSize());
+		}
+		*/
+		
+		if ((text != null) && (text.length() > 0)) {
+			Font font = label.getFont();
+			if (font == null) {
+				font = Display.getDefault().getSystemFont();
+			}
+			Dimension textSize = FigureUtilities.getStringExtents(text, font); 
+			minSize.expand(textSize.width + 8, Math.max(0, textSize.height + 4 - minSize.height));
+		}
+		if (label.getIcon() != null) {
+			org.eclipse.swt.graphics.Rectangle imageRect = label.getIcon().getBounds();
+			minSize.expand(imageRect.width + 8, Math.max(0, imageRect.height + 6 - minSize.height));
+		}
+		return minSize;
+	}
+	
+	/*public boolean isVisible() {
+		return true;
+	}
+	*/
+
+	
+	public boolean isCoordinateSystem() {
+		// TODO Auto-generated method stub
+		return true;
+	}
+	
+
+	
+	
+	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#setBounds(org.eclipse.draw2d.geometry.Rectangle)
+	 */
+	
+	public static final int XSIZE = 500;
+	public static final int YSIZE = 500;
+	
+	
+	public void setBounds(Rectangle bounds) {
+		// resize the label & nested figures
+		//int XSIZE = clienRectangle.width;
+		//int YSIZE = clienRectangle.height;
+		if ( XSIZE == 0 || YSIZE == 0 ) {
+			super.setBounds(bounds);
+			return;
+		}		
+		int width = bounds.width;
+		int height = bounds.height;
+		Dimension labelSize = label.getSize();
+		
+		//@tag bug(unreported(Clipped-Labels(fix))) : always calculate the size of the label, otherwise they get clipped when the bounds are too small.
+		labelSize = calculateLabelSize();
+		
+		int labelHeight = Math.min(height, labelSize.height);
+		labelSize.setSize(new Dimension(width, labelHeight));
+		Point labelLoc = new Point(0, 0);
+		getLayoutManager().setConstraint(label, new Rectangle(labelLoc, labelSize));		
+		
+		Point location = new Point(0, labelSize.height);
+		double xScale = (double)width / (double) XSIZE;
+		double yScale = (double)(height-labelHeight) / (double)YSIZE;		
+		getLayoutManager().setConstraint(scaledFigure, new Rectangle(location.x, location.y ,width, height));
+		scaledFigure.setScale(xScale, yScale);
+		super.setBounds(bounds);
+	}
+	
+
+	public Label getLabel() {
+		return label;
+	}
+	
+	public AspectRatioScaledFigure getScaledFigure() {
+		return scaledFigure;
+	}
+	
+	protected boolean useLocalCoordinates() {
+		return true;
+	}	
+
+	/** 
+	 * Adds any NestedFigure objects to the NestedFigure instead.
+	 * @see org.eclipse.draw2d.Figure#add(org.eclipse.draw2d.IFigure, java.lang.Object, int)
+	 */
+	public void add(IFigure figure, Object constraint, int index) {
+		if (figure instanceof NestedFigure) {
+			NestedFigure nestedFigure = (NestedFigure)figure;
+			scaledFigure.add(nestedFigure, constraint, index);
+		} else {
+			super.add(figure, constraint, index);
+		}
+	}
+	
+	/**
+	 * Sets the background color of the <b>label</b>.  If you want to set the background
+	 * color for the nested figures then call {@link #getScaledFigure().setBackgroundColor(Color)}.
+	 */
+	public void setBackgroundColor(Color bg) {
+		label.setBackgroundColor(bg);
+		/*[irbull]
+		if (button != null) {
+			button.setBackgroundColor(bg);
+		}
+		*/
+	}
+	
+	/**
+	 * Sets the foreground color of the <b>label</b>.
+	 */
+	public void setForegroundColor(Color fg) {
+		label.setForegroundColor(fg);
+		/*[irbull]
+		if (button != null) {
+			button.setForegroundColor(fg);
+		}
+		*/
+	}
+	
+	/**
+	 * Sets the scale of the ScaledFigure.
+	 * @param scale the scale
+	 */
+	public void setScale(double wScale, double hScale) {
+		scaledFigure.setScale(wScale, hScale);
+	}
+	
+	/**
+	 * Gets the scale of the ScaledFigure.
+	 * @return double the scale
+	 */
+	/*
+	public double getScale() {
+		return scaledFigure.getScale();
+	}
+	*/
+	public double getWidthScale() {
+		return scaledFigure.getWidthScale();
+	}
+	
+	public double getHeightScale() {
+		return scaledFigure.getHeightScale();
+	}
+
+	
+	public double calculateTotalWidthScale() {
+		double scale = getWidthScale();
+		NestedFigure fig = this;
+		while ( ( fig.getParent() instanceof AspectRatioScaledFigure ) && ( fig.getParent().getParent() instanceof NestedFigure ) ) {
+			fig = (NestedFigure)fig.getParent().getParent();
+			scale *= fig.getWidthScale();
+		}
+		return scale;
+	}
+	
+	
+	public double calculateTotalHeightScale() {
+		double scale = getHeightScale();
+		NestedFigure fig = this;
+		while ( ( fig.getParent() instanceof AspectRatioScaledFigure ) && ( fig.getParent().getParent() instanceof NestedFigure ) ) {
+			fig = (NestedFigure)fig.getParent().getParent();
+			scale *= fig.getHeightScale();
+		}
+		return scale;
+	}
+
+	
+	/**
+	 * Calculates the total scale for this figure.  It traverses up the
+	 * parent hierarchy multiplying the scales of each NestedFigure.
+	 * @return double
+	 */
+	/*
+	public double calculateTotalScale() {
+		double scale = getScale();
+		NestedFigure fig = this;
+		while ((fig.getParent() instanceof ScaledFigure) && (fig.getParent().getParent() instanceof NestedFigure)) {
+			fig = (NestedFigure)fig.getParent().getParent();
+			scale *= fig.getScale();
+		}
+		return scale;
+	}
+	*/
+	
+	/**
+	 * Sets the visibility of the nested figures.
+	 * @param visible
+	 */
+	public void setNestedFiguresVisible(boolean visible) {
+		/*[irbull]
+		if ((button != null) && (button.isSelected() != visible)) {
+			button.setSelected(visible);
+		}
+		*/
+		/*
+		for (Iterator iter = children.iterator(); iter.hasNext();) {
+			IFigure element = (IFigure) iter.next();
+			//element.setVisible(visible);
+		}
+		*/
+		scaledFigure.setVisible(visible);
+		//scaledFigure.setVisible(visible);
+		//scaledFigure.setFlag(Figure.FLAG_VISIBLE, visible);
+		/*
+		scaledFigure.erase();
+		scaledFigure.repaint();
+		scaledFigure.revalidate();
+		
+		scaledFigure.repaint();
+		revalidate();
+		*/
+		
+		//scaledFigure.revalidate();
+		//scaledFigure.setVisible(visible);
+	}
+		
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		return "NestedFigure " + label.getText();
+	}
+
+	
+}
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/OutlineFigure.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/OutlineFigure.java
new file mode 100644
index 0000000..0f17b65
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/OutlineFigure.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.RectangleFigure;
+
+
+/**
+ * A rectangular figure which has a dotted outline and no fill.
+ * 
+ * @author Chris Callendar
+ */
+public class OutlineFigure extends RectangleFigure {
+
+	/**
+	 * 
+	 */
+	public OutlineFigure() {
+		super();
+		setOpaque(false);
+		setFill(false);
+		setXOR(false);
+		super.setOutline(true);
+		setLineStyle(Graphics.LINE_DOT);
+	}
+
+	/**
+	 * Does nothing.  True by default.
+	 * @see org.eclipse.draw2d.Shape#setOutline(boolean)
+	 */
+	public void setOutline(boolean b) {
+		// does nothing
+	}
+	
+	/**
+	 * Does nothing.
+	 * @see org.eclipse.draw2d.RectangleFigure#fillShape(org.eclipse.draw2d.Graphics)
+	 */
+	protected void fillShape(Graphics graphics) {
+		// do nothing
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.RectangleFigure#outlineShape(org.eclipse.draw2d.Graphics)
+	 */
+	protected void outlineShape(Graphics graphics) {
+		graphics.setBackgroundColor(getBackgroundColor());
+		graphics.setForegroundColor(getForegroundColor());
+		super.outlineShape(graphics);
+	}
+	
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/PaneFigure.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/PaneFigure.java
new file mode 100644
index 0000000..b19b5a3
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/PaneFigure.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+import org.eclipse.draw2d.ActionEvent;
+import org.eclipse.draw2d.ActionListener;
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.FreeformLayout;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Label;
+import org.eclipse.draw2d.Panel;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedPane;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts.FigureGridLayout;
+import org.eclipse.mylar.zest.core.messages.ZestUIMessages;
+
+/**
+ * 
+ * Basic figure for creating panes in the nested graph viewer. Can be one of
+ * three types: NestedPane.SUPPLIER_PANE, NestedPane.CLIENT_PANE,
+ * or NestedPain.MAIN_PANE. The main pane contains the nested graph element that
+ * the user is currently focussed on. The supplier pane contains all nodes that
+ * have arcs running "from" that node "to" the focus node, or any of its children.
+ * The client pane contains all nodes that have arcs running "to" that node "from"
+ * the focus node or any of its children.
+ * @author Del Myers
+ */
+
+//@tag zest(bug(152613-Client-Supplier(fix))) : the basic panes that will contain the nested graphs.
+public class PaneFigure extends Panel {
+	private static final int ICON_SIZE = 16;
+	private Label label;
+	private MinMaxFigure minMax;
+	private Panel clientArea;
+	private int type;
+	public PaneFigure(int type) {
+		super();
+		this.type = type;
+		clientArea = new Panel();
+		
+		setLayoutManager(new FreeformLayout(){
+			/* (non-Javadoc)
+			 * @see org.eclipse.draw2d.XYLayout#layout(org.eclipse.draw2d.IFigure)
+			 */
+			public void layout(IFigure parent) {
+				Rectangle textbounds = (label != null) ? label.getTextBounds() : new Rectangle(0,0,0,0);
+				
+				Rectangle parentBounds = parent.getBounds();
+				if (label != null) label.setSize(parent.getSize().width, textbounds.height);
+				clientArea.setBounds(new Rectangle(parentBounds.x, parentBounds.y+textbounds.height, parent.getSize().width, parent.getSize().height-textbounds.height));
+				//@tag zest(bug(152613-Client-Supplier(fix))) : allow the icon to have a say in the size of the figure.
+				if (minMax != null) {
+					Object constraint = getConstraint(minMax);
+					if (constraint instanceof Dimension) {
+						Dimension d = (Dimension)constraint;
+						minMax.setBounds(new Rectangle(parentBounds.x+parentBounds.width-d.width, parentBounds.y, d.width, d.height));
+						label.setSize(label.getSize().width, d.height);
+					}
+				}
+			}
+			
+			/* (non-Javadoc)
+			 * @see org.eclipse.draw2d.AbstractLayout#getPreferredSize(org.eclipse.draw2d.IFigure, int, int)
+			 */
+			//@tag zest(bug(152613-Client-Supplier(fix))) : preferred size should be set by the layout manager, as it is what is doing the layout.
+			public Dimension getPreferredSize(IFigure container, int wHint, int hHint) {
+				int labelHeight = 0;
+				int labelWidth = wHint;
+				int clientHeight = 0;
+				if (label != null) {
+					labelHeight = label.getTextBounds().height;
+					labelWidth = label.getTextBounds().width;
+					if (minMax != null && minMax.getSize().height > labelHeight) {
+						labelHeight = minMax.getSize().height;
+					}
+				}
+				if (!isClosed()) {
+					if (hHint >= labelHeight) {
+						clientHeight = hHint-labelHeight;
+					}
+				}
+				return new Dimension(labelWidth, labelHeight+clientHeight);
+			}
+		});
+		clientArea.setBackgroundColor(ColorConstants.white);
+		clientArea.setLayoutManager(new FigureGridLayout());
+		clientArea.setOpaque(true);
+		super.add(clientArea, null, -1);
+		if (type != NestedPane.MAIN_PANE) {
+			label = new Label();
+			label.setBackgroundColor(ColorConstants.darkBlue);
+			label.setText(getTextForType(type));
+			label.setOpaque(true);
+			label.setForegroundColor(ColorConstants.lightGray);
+			minMax = new MinMaxFigure();
+			super.add(label, null, -1);
+			super.add(minMax, new Dimension(ICON_SIZE, ICON_SIZE), -1);
+			minMax.setVisible(true);
+			minMax.addActionListener(new ActionListener(){
+				public void actionPerformed(ActionEvent event) {
+					invalidateTree();
+					revalidate();
+				}});
+		}
+		
+		invalidate();
+		
+	}
+	/**
+	 * @param paneType2
+	 * @return
+	 */
+	private String getTextForType(int paneType) {
+		switch(paneType) {
+		case NestedPane.CLIENT_PANE: return ZestUIMessages.VIEW_NESTED_CLIENT_PANE;
+		case NestedPane.SUPPLIER_PANE: return ZestUIMessages.VIEW_NESTED_SUPPLIER_PANE;
+		}
+		return "";
+	}
+	
+	public Panel getClientPanel() {
+		return clientArea;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#add(org.eclipse.draw2d.IFigure, java.lang.Object, int)
+	 */
+	public void add(IFigure figure, Object constraint, int index) {
+		//add to the client area so that the title is visible.
+		clientArea.add(figure, constraint, index);
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#remove(org.eclipse.draw2d.IFigure)
+	 */
+	public void remove(IFigure figure) {
+		if (clientArea.getChildren().contains(figure)){
+			clientArea.remove(figure);
+			return;
+		}
+		super.remove(figure);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#removeAll()
+	 *
+	public void removeAll() {
+		clientArea.removeAll();
+	}*/
+	
+	/**
+	 * @return the type
+	 */
+	public int getType() {
+		return type;
+	}
+	
+	/**
+	 * Allows the pane to be open or to be closed. This is only valid in
+	 * SUPPLIER_PANE and CLIENT_PANE types.
+	 * @param closed whether or not the content pane should be closed.
+	 */
+	public void setClosed(boolean closed) {
+		if (closed != isClosed()) {
+			if (minMax != null) {
+				minMax.setMax(closed);
+				invalidate();
+			}
+		}
+	}
+	
+	/**
+	 * 
+	 * @return whether or not the content pane is closed.
+	 */
+	public boolean isClosed() {
+		return (minMax != null && minMax.isMax());
+	}
+	
+	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#getClientArea(org.eclipse.draw2d.geometry.Rectangle)
+	 */
+/*	public Rectangle getClientArea(Rectangle rect) {
+		Rectangle client = getClientPanel().getClientArea();
+		rect.x = client.x;
+		rect.y = client.y;
+		rect.width = client.width;
+		rect.height = client.height;
+		return rect;
+	}*/
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/PlusMinusFigure.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/PlusMinusFigure.java
new file mode 100644
index 0000000..ce1172f
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/PlusMinusFigure.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+import org.eclipse.draw2d.ActionListener;
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.Toggle;
+import org.eclipse.draw2d.geometry.Insets;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.mylar.zest.core.IZestColorConstants;
+import org.eclipse.mylar.zest.core.ZestPlugin;
+
+
+/**
+ * A plus/minus toggle figure.
+ * @author Chris Callendar
+ */
+public class PlusMinusFigure extends Toggle {
+	
+	public PlusMinusFigure() {
+		this(16);
+	}
+	
+	/**
+	 * Initializes this figure with the given listener (for 
+	 * being notified when the figure is toggled).
+	 * @param plusSize The plus size
+	 */
+	public PlusMinusFigure(int plusSize) {
+		setPreferredSize(plusSize, plusSize);		
+	}
+	
+	/**
+	 * Adds an action listener to be notified when the PlusMinusFigure is toggled.
+	 * @see org.eclipse.draw2d.Clickable#addActionListener(org.eclipse.draw2d.ActionListener)
+	 */
+	public void addActionListener(ActionListener listener) {
+		if (listener != null) {
+			super.addActionListener(listener);
+		}
+	}
+
+	/**
+	 * @see org.eclipse.draw2d.Figure#paintFigure(org.eclipse.draw2d.Graphics)
+	 */
+	protected void paintFigure(Graphics g) {
+		super.paintFigure(g);
+		
+		Rectangle r = Rectangle.SINGLETON;
+		r.setBounds(getBounds());
+		g.fillRectangle(r);
+		
+		Insets insets = getInsets();
+		if (!insets.isEmpty()) {
+			r.resize(0 - (insets.left + insets.right), 0 - (insets.top + insets.bottom));
+			r.translate(insets.left, insets.top);
+		}
+		// define a square for the border
+		if (r.width <= r.height) {
+			r.y = r.y + (r.height - r.width) / 2;
+			r.height = r.width;
+		} else {
+			r.x = r.x + (r.width - r.height) / 2;
+			r.width = r.height;
+		}
+		g.setBackgroundColor(ColorConstants.white);
+		g.fillRectangle(r);
+//		@tag zest(bug(151332-Colors(fix)))
+		g.setForegroundColor(ZestPlugin.getDefault().getColor(IZestColorConstants.LIGHT_BLUE_CYAN));
+		g.drawRectangle(new Rectangle(r.x+1, r.y+1, r.width-1, r.height-1));
+//		@tag zest(bug(151332-Colors(fix)))
+		g.setForegroundColor(ZestPlugin.getDefault().getColor(IZestColorConstants.GREY_BLUE));
+		g.drawRectangle(r);
+		
+		int xMid = r.x + r.width / 2;
+		int yMid = r.y + r.height / 2;
+//		@tag zest(bug(151332-Colors(fix)))
+		g.setForegroundColor(ZestPlugin.getDefault().getColor(IZestColorConstants.LIGHT_BLUE_CYAN));
+		g.drawLine(r.x + 3, yMid+1, r.right() - 2, yMid+1);
+		//@tag zest(bug(153368(fix))) : draw plus when selected.
+		if (isSelected()) {
+			g.drawLine(xMid+1, r.y + 3, xMid+1, r.bottom() - 2);
+		}
+//		@tag zest(bug(151332-Colors(fix)))
+		g.setForegroundColor(ZestPlugin.getDefault().getColor(IZestColorConstants.DARK_BLUE));
+		//@tag zest(bug(153368(fix))) : draw plus when selected
+		g.drawLine(r.x + 2, yMid, r.right() - 2, yMid);
+		if (isSelected()) {
+			g.drawLine(xMid, r.y + 2, xMid, r.bottom() - 2);
+		}
+		
+			
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/RoundedChopboxAnchor.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/RoundedChopboxAnchor.java
new file mode 100644
index 0000000..63c9c57
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/RoundedChopboxAnchor.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+import org.eclipse.draw2d.ChopboxAnchor;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+/**
+ * A slight modification to the ChopboxAnchor class to account for the rounded corners.
+ * 
+ * @author Chris Callendar
+ */
+public class RoundedChopboxAnchor extends ChopboxAnchor {
+
+	private int arcRadius = 10;
+	private int shift = 7;
+	
+	public RoundedChopboxAnchor(int arcRadius) {
+		super();
+		this.arcRadius = arcRadius;
+		this.shift = arcRadius - (int)(0.707 * arcRadius);
+	}
+
+	public RoundedChopboxAnchor(IFigure owner, int arcRadius) {
+		super(owner);
+		this.arcRadius = arcRadius;
+		this.shift = arcRadius - (int)(0.707 * arcRadius);
+	}
+
+	/**
+	 * Modifies the point slightly for the rounded corners.
+	 * @return Point
+	 */
+	public Point getLocation(Point reference) {
+		Point p = super.getLocation(reference);
+		Rectangle bounds = getBox();
+		
+		boolean done = getTranslatedPoint(bounds.getTopLeft(), p, shift, shift);
+		if (!done)
+			done = getTranslatedPoint(bounds.getTopRight(), p, -shift, shift);
+		if (!done)
+			done = getTranslatedPoint(bounds.getBottomLeft(), p, shift, -shift);
+		if (!done)
+			done = getTranslatedPoint(bounds.getBottomRight(), p, -shift, -shift);
+		return p;
+	}
+	
+	/**
+	 * Calculates the distance from the corner to the Point p.  
+	 * If it is less than the minimum then it translates it and returns the new Point.
+	 * @param corner	The corner Point.
+	 * @param p			The point to translate if close to the corner.
+	 * @param dx		The amount to translate in the x direcion.
+	 * @param dy		The amount to translate in the y direcion.
+	 * @return boolean 	If the translation occured.
+	 */
+	private boolean getTranslatedPoint(Point corner, Point p, int dx, int dy) {
+		int diff = (int)corner.getDistance(p);
+		if (diff < arcRadius) {
+			Point t = corner.getTranslated(dx, dy);
+			p.setLocation(t.x, t.y);
+			return true;
+		}
+		return false;
+	}
+	
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/ScaledFigure.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/ScaledFigure.java
new file mode 100644
index 0000000..351ae79
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/ScaledFigure.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+
+import org.eclipse.draw2d.Figure;
+import org.eclipse.draw2d.FreeformLayout;
+import org.eclipse.draw2d.Graphics;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.ScaledGraphics;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.draw2d.geometry.Translatable;
+
+/**
+ * A freeform layer figure which can be scaled.
+ * 
+ * @author Ian Bull
+ * @author Chris Callendar
+ */
+public class ScaledFigure extends Figure {
+
+	private double scale = 1D;
+
+	
+
+	
+	
+	public ScaledFigure() {
+		scale = 1D;
+		setLayoutManager(new FreeformLayout());
+		setOpaque(true);
+	}
+	
+	public void setScale(double scale) {
+		this.scale = scale;
+		revalidate();
+		repaint();
+	}
+	
+	public double getScale() {
+		return this.scale;
+	}
+	
+	/**
+	 * @see org.eclipse.draw2d.Figure#getClientArea()
+	 */
+	public Rectangle getClientArea(Rectangle rect) {
+		super.getClientArea(rect);
+		rect.width /= scale;
+		rect.height /= scale;
+		return rect;
+	}
+
+	public Dimension getPreferredSize(int wHint, int hHint) {
+		Dimension d = super.getPreferredSize(wHint, hHint);
+		int w = getInsets().getWidth();
+		int h = getInsets().getHeight();
+		return d.getExpanded(-w, -h).scale(scale).expand(w,h);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#translateFromParent(org.eclipse.draw2d.geometry.Translatable)
+	 */
+	public void translateFromParent(Translatable t) {
+		super.translateFromParent(t);
+		t.performScale(1/scale);		
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#translateToParent(org.eclipse.draw2d.geometry.Translatable)
+	 */
+	public void translateToParent(Translatable t) {
+		t.performScale(scale);
+		super.translateToParent(t);
+	}
+
+	protected boolean useLocalCoordinates() {
+		return true;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.draw2d.Figure#paintClientArea(org.eclipse.draw2d.Graphics)
+	 */
+	protected void paintClientArea(Graphics graphics) {
+		if (getChildren().isEmpty())
+			return;
+
+		ScaledGraphics g = null;
+		boolean disposeGraphics = false;
+		if (graphics instanceof ScaledGraphics) {
+			g = (ScaledGraphics)graphics;
+		} else {
+			g = new ScaledGraphics(graphics);
+			disposeGraphics = true;
+		}
+		
+		boolean optimizeClip = getBorder() == null || getBorder().isOpaque();
+		if (!optimizeClip) {
+			g.clipRect(getBounds().getCropped(getInsets()));
+		}
+		g.translate(getBounds().x + getInsets().left, getBounds().y + getInsets().top);
+		g.scale(scale);
+		g.pushState();
+		paintChildren(g);
+		g.popState();
+		if (disposeGraphics) {
+			g.dispose();
+			graphics.restoreState();
+		}
+	}
+	
+	public void add(IFigure figure, Object constraint, int index) {
+		super.add(figure, constraint, index);
+	}	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/SimpleLabelBox.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/SimpleLabelBox.java
new file mode 100644
index 0000000..55cb1c3
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/figures/SimpleLabelBox.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.figures;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.draw2d.FreeformLayout;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Label;
+import org.eclipse.draw2d.LineBorder;
+import org.eclipse.draw2d.Panel;
+import org.eclipse.draw2d.geometry.Rectangle;
+
+/**
+ * A simple box with a label.
+ * @author Del Myers
+ *
+ */
+//@tag zest(bug(153466-NoNestedClientSupply(fix))) : create a simple label box for the nodes.
+public class SimpleLabelBox extends Panel {
+	private Label label;
+	private Panel contentPane;
+	public SimpleLabelBox() {
+		super();
+		label = new Label();
+		setLayoutManager(new FreeformLayout(){
+			/* (non-Javadoc)
+			 * @see org.eclipse.draw2d.XYLayout#layout(org.eclipse.draw2d.IFigure)
+			 */
+			public void layout(IFigure parent) {
+				Rectangle textbounds = (label != null) ? label.getTextBounds() : new Rectangle(0,0,0,0);
+				
+				Rectangle parentBounds = parent.getBounds();
+				if (label != null) label.setSize(parent.getSize().width, textbounds.height);
+				contentPane.setBounds(new Rectangle(parentBounds.x, parentBounds.y+textbounds.height, parent.getSize().width, parent.getSize().height-textbounds.height));
+				
+			}
+		});
+		contentPane = new Panel();
+		contentPane.setBackgroundColor(ColorConstants.white);
+		contentPane.setOpaque(true);
+		add(label);
+		add(contentPane);
+		setBackgroundColor(ColorConstants.black);
+		setForegroundColor(ColorConstants.black);
+		setBorder(new LineBorder(ColorConstants.black));
+		setOpaque(false);
+	}
+	
+	/**
+	 * @return the label
+	 */
+	public Label getLabel() {
+		return label;
+	}
+	
+	/**
+	 * @return the contentPane
+	 */
+	public Panel getContentPane() {
+		return contentPane;
+	}
+	
+	public String toString() {
+		return label.getText();
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/trackers/PanningTracker.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/trackers/PanningTracker.java
new file mode 100644
index 0000000..708e297
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/trackers/PanningTracker.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.trackers;
+
+import org.eclipse.draw2d.FigureCanvas;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.gef.RootEditPart;
+import org.eclipse.gef.SharedCursors;
+import org.eclipse.gef.commands.Command;
+import org.eclipse.mylar.zest.core.internal.gefx.IPanningListener;
+import org.eclipse.mylar.zest.core.internal.viewers.commands.PanningCommand;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.graphics.Cursor;
+
+
+
+/**
+ * Panning drag tracker (single selection only).
+ * 
+ * @author Chris Callendar
+ */
+public class PanningTracker extends SingleSelectionTracker {
+
+	private IPanningListener panningListener;
+	private boolean allowPanning = true;
+	private boolean panningStarted = false;
+	private Point lastLocation;
+
+	/**
+	 * PanningTracker constructor.
+	 */
+	public PanningTracker(RootEditPart source, IPanningListener panningListener, boolean allowPanning) {
+		super(source);
+		this.panningListener = panningListener;
+		this.allowPanning = allowPanning;
+		this.lastLocation = new Point(0, 0);
+	}
+
+	/**
+	 * @see org.eclipse.gef.tools.AbstractTool#getDebugName()
+	 */
+	protected String getDebugName() {
+		return "PanningTracker";
+	}
+	
+	/**
+	 * Gets the figure canvas. If the current viewer's control is not a figure canvas then null is returned.
+	 * @return the figure canvas from the current viewer's control
+	 */
+	protected FigureCanvas getCanvas() {
+		if (getCurrentViewer().getControl() instanceof FigureCanvas) {
+			return (FigureCanvas) getCurrentViewer().getControl();
+		}
+		return null;
+	}
+
+	/**
+	 * Returns the cursor used under normal conditions.
+	 * If panning has started a HAND cursor is returned.
+	 * @return the default cursor
+	 */
+	protected Cursor getDefaultCursor() {
+		if (panningStarted) {
+			return SharedCursors.HAND;
+		}
+		return super.getDefaultCursor();
+	}
+
+	
+	/**
+	 * Gets a {@link PanningCommand} if panning has started.  This is used 
+	 * to have a HAND cursor instead of a disabled one.
+	 * @see org.eclipse.gef.tools.DragEditPartsTracker#getCommand()
+	 */
+	protected Command getCommand() {
+		if (panningStarted) {
+			return new PanningCommand();
+		}
+		return super.getCommand();
+	}
+	
+	/**
+	 * Instead of giving the <b>total</b> drag distance this returns
+	 * the distance since the last time handleDragStarted() or handleDrag()
+	 * was called.  
+	 */
+	private Dimension getPanningDelta() {
+		Dimension diff = getLocation().getDifference(lastLocation);
+		return diff;
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.gef.tools.AbstractTool#handleDrag()
+	 */
+	protected boolean handleDrag() {
+		if (panningStarted && (getCanvas() != null)) {
+			panningListener.panning(getPanningDelta().width, getPanningDelta().height);
+			lastLocation = getLocation();
+			return true;
+		} else {
+			return super.handleDrag();
+		}
+	}
+
+	/**
+	 * If panning is allowed then the source editpart viewer is signalled
+	 * about the start of panning and the cursor is changed to a HAND cursor. 
+	 * @see org.eclipse.gef.tools.AbstractTool#handleDragStarted()
+	 */
+	protected boolean handleDragStarted() {
+		if (allowPanning) {
+			panningListener.panningStart();
+			panningStarted = true;
+			lastLocation = getLocation();
+			refreshCursor();
+			return true;
+		}
+		return super.handleDragStarted();
+	}
+	
+	/**
+	 * Indicates that the panning has stopped if the button is 1.  
+	 * @see org.eclipse.gef.tools.DragEditPartsTracker#handleButtonUp(int)
+	 */
+	protected boolean handleButtonUp(int button) {
+		if (button == 1) {
+			panningStarted = false;
+			if (allowPanning) {
+				panningListener.panningEnd();
+			}
+		}
+		return super.handleButtonUp(button);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.tools.DragEditPartsTracker#handleKeyDown(org.eclipse.swt.events.KeyEvent)
+	 */
+	protected boolean handleKeyDown(KeyEvent e) {
+		//System.out.println("PanningTracker: keyDown: " + e.toString());
+		return super.handleKeyDown(e);
+	}
+		
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/trackers/SingleSelectionTracker.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/trackers/SingleSelectionTracker.java
new file mode 100644
index 0000000..b0bbd58
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/internal/viewers/trackers/SingleSelectionTracker.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.internal.viewers.trackers;
+
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.tools.DragEditPartsTracker;
+
+/**
+ * The SingleSelectionTracker is similar to the org.eclipse.gef.internal.ui.palette.editparts.SingleSelectionTracker
+ * class.
+ * 
+ * @author Chris Callendar
+ */
+public class SingleSelectionTracker extends DragEditPartsTracker {
+
+	/**
+	 * Initializes this drag tracker.
+	 * @param source	Owner edit part.
+	 */
+	public SingleSelectionTracker(EditPart source) {
+		super(source);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.tools.DragEditPartsTracker#getDebugName()
+	 */
+	protected String getDebugName() {
+		return "SingleSelectionTracker";
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.gef.tools.SelectEditPartTracker#performSelection()
+	 */
+	protected void performSelection() {
+		if (hasSelectionOccurred())
+			return;
+		setFlag(FLAG_SELECTION_PERFORMED, true);
+		getCurrentViewer().select(getSourceEditPart());
+	}
+		
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/messages/ZestError.properties b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/messages/ZestError.properties
new file mode 100644
index 0000000..89f097d
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/messages/ZestError.properties
@@ -0,0 +1,3 @@
+error.invalid.input=The given input is invalid for the viewer.
+error.cannot.set.sytle=The style could not be set. Null input expected.
+error.invalid.style=The style could not be set. Style is invalid.
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/messages/ZestErrorMessages.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/messages/ZestErrorMessages.java
new file mode 100644
index 0000000..5b48bd0
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/messages/ZestErrorMessages.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.messages;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+
+
+/**
+ * Messages for internationalized strings pertaining to errors.
+ * @author Del Myers
+ * @see org.eclipse.mylar.zest.ZestException
+ *
+ */
+public class ZestErrorMessages {
+	private static final String BUNDLE_NAME =
+		"org.eclipse.mylar.zest.core.messages.ZestError"; //$NON-NLS-1$
+	private static final ResourceBundle BUNDLE =
+		ResourceBundle.getBundle(BUNDLE_NAME);
+	public static final String ERROR_INVALID_INPUT =
+		getString("error.invalid.input"); //$NON-NLS-1$
+	public static final String ERROR_CANNOT_SET_STYLE =
+		getString("error.cannot.set.style"); //$NON-NLS-1$
+	public static final String ERROR_INVALID_STYLE =
+		getString("error.invalid.style"); //$NON-NLS-1$
+		
+	
+	
+	public static String getString(String key) {
+		try {
+			return BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+	         return "!" + key + "!";
+	     }
+
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/messages/ZestUI.properties b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/messages/ZestUI.properties
new file mode 100644
index 0000000..a853b9b
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/messages/ZestUI.properties
@@ -0,0 +1,5 @@
+view.nested.top.node=Top Level Node
+view.nested.client.pane=Connected To
+view.nested.supplier.pane=Connected From
+tip.minimize=Minimize
+tip.maximize=Maximize
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/messages/ZestUIMessages.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/messages/ZestUIMessages.java
new file mode 100644
index 0000000..2096bb6
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/messages/ZestUIMessages.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.messages;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+
+
+/**
+ * Messages for internationalized strings pertaining to ui elements.
+ * @author Del Myers
+ * @see org.eclipse.mylar.zest.ZestException
+ *
+ */
+public class ZestUIMessages {
+	private static final String BUNDLE_NAME =
+		"org.eclipse.mylar.zest.core.messages.ZestUI"; //$NON-NLS-1$
+	private static final ResourceBundle BUNDLE =
+		ResourceBundle.getBundle(BUNDLE_NAME);
+	public static final String VIEW_NESTED_TOP_NODE =
+		getString("view.nested.top.node"); //$NON-NLS-1$
+	public static final String VIEW_NESTED_CLIENT_PANE =
+		getString("view.nested.client.pane"); //$NON-NLS-1$
+	public static final String VIEW_NESTED_SUPPLIER_PANE =
+		getString("view.nested.supplier.pane"); //$NON-NLS-1$
+	public static final String TIP_MINIMIZE = 
+		getString("tip.minimize");
+	public static final String TIP_MAXIMIZE = 
+		getString("tip.maximize");
+	
+	
+	public static String getString(String key) {
+		try {
+			return BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+	         return "!" + key + "!";
+	     }
+
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/AbstractStructuredGraphViewer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/AbstractStructuredGraphViewer.java
new file mode 100644
index 0000000..4e24f8e
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/AbstractStructuredGraphViewer.java
@@ -0,0 +1,636 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
+
+import org.eclipse.gef.EditPart;
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.mylar.zest.core.ZestException;
+import org.eclipse.mylar.zest.core.ZestPlugin;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphItem;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModelConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphItem;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelConnection;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IZestGraphDefaults;
+import org.eclipse.mylar.zest.layouts.LayoutAlgorithm;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Abstraction of graph viewers to implement functionality used by all of them.
+ * Not intended to be implemented by clients. Use one of the provided children
+ * instead.
+ * 
+ * @author Del Myers
+ * 
+ */
+public abstract class AbstractStructuredGraphViewer extends AbstractZoomableViewer {
+	/**
+	 * Contains top-level styles for the entire graph. Set in the constructor. *
+	 */
+	private int graphStyle;
+
+	/**
+	 * Contains node-level styles for the graph. Set in setNodeStyle(). Defaults
+	 * are used in the constructor.
+	 */
+	private int nodeStyle;
+
+	/**
+	 * Contains arc-level styles for the graph. Set in setConnectionStyle().
+	 * Defaults are used in the constructor.
+	 */
+	private int connectionStyle;
+
+	/**
+	 * The main graph model
+	 */
+	private GraphModel model;
+
+	/**
+	 * A simple graph comparator that orders graph elements based on thier type
+	 * (connection or node), and their unique object identification.
+	 */
+	private class SimpleGraphComparator implements Comparator {
+		TreeSet storedStrings;
+
+		/**
+		 * 
+		 */
+		public SimpleGraphComparator() {
+			this.storedStrings = new TreeSet();
+		}
+
+		/*
+		 * (non-Javadoc)
+		 * 
+		 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+		 */
+		public int compare(Object arg0, Object arg1) {
+			if (arg0 instanceof IGraphModelNode
+					&& arg1 instanceof IGraphModelConnection) {
+				return 1;
+			} else if (arg0 instanceof IGraphModelConnection
+					&& arg1 instanceof IGraphModelNode) {
+				return -1;
+			}
+			if (arg0.equals(arg1))
+				return 0;
+			return getObjectString(arg0).compareTo(getObjectString(arg1));
+		}
+
+		private String getObjectString(Object o) {
+			String s = o.getClass().getName() + "@"
+					+ Integer.toHexString(o.hashCode());
+			while (storedStrings.contains(s)) {
+				s = s + 'X';
+			}
+			return s;
+		}
+	}
+
+	protected AbstractStructuredGraphViewer(int graphStyle) {
+		this.graphStyle = graphStyle;
+		this.connectionStyle = IZestGraphDefaults.CONNECTION_STYLE;
+		this.nodeStyle = IZestGraphDefaults.NODE_STYLE;
+	}
+
+	/**
+	 * Sets the default style for nodes in this graph. Note: if an input is set
+	 * on the viewer, a ZestException will be thrown.
+	 * 
+	 * @param nodeStyle
+	 *            the style for the nodes.
+	 * @see #ZestStyles
+	 */
+	public void setNodeStyle(int nodeStyle) {
+		if (getInput() != null)
+			ZestPlugin.error(ZestException.ERROR_CANNOT_SET_STYLE);
+		this.nodeStyle = nodeStyle;
+	}
+
+	/**
+	 * Sets the default style for connections in this graph. Note: if an input
+	 * is set on the viewer, a ZestException will be thrown.
+	 * 
+	 * @param connectionStyle
+	 *            the style for the connections.
+	 * @see #ZestStyles
+	 */
+	public void setConnectionStyle(int connectionStyle) {
+		if (getInput() != null)
+			ZestPlugin.error(ZestException.ERROR_CANNOT_SET_STYLE);
+		if (!ZestStyles.validateConnectionStyle(connectionStyle))
+			ZestPlugin.error(ZestException.ERROR_INVALID_STYLE);
+		this.connectionStyle = connectionStyle;
+	}
+
+	/**
+	 * Returns the style set for the graph
+	 * 
+	 * @return The style set of the graph
+	 */
+	public int getGraphStyle() {
+		return graphStyle;
+	}
+
+	/**
+	 * Returns the style set for the nodes.
+	 * 
+	 * @return the style set for the nodes.
+	 */
+	public int getNodeStyle() {
+		return nodeStyle;
+	}
+
+	/**
+	 * @return the connection style.
+	 */
+	public int getConnectionStyle() {
+		return connectionStyle;
+	}
+
+	/**
+	 * Sets the layout algorithm for this viewer. Subclasses may place
+	 * restrictions on the algorithms that it accepts.
+	 * 
+	 * @param algorithm
+	 *            the layout algorithm
+	 * @param run
+	 *            true if the layout algorithm should be run immediately. This
+	 *            is a hint.
+	 */
+	public abstract void setLayoutAlgorithm(LayoutAlgorithm algorithm,
+			boolean run);
+
+	/**
+	 * Gets the current layout algorithm.
+	 * 
+	 * @return the current layout algorithm.
+	 */
+	protected abstract LayoutAlgorithm getLayoutAlgorithm();
+
+	/**
+	 * Equivalent to setLayoutAlgorithm(algorithm, false).
+	 * 
+	 * @param algorithm
+	 */
+	public void setLayoutAlgorithm(LayoutAlgorithm algorithm) {
+		setLayoutAlgorithm(algorithm, false);
+	}
+
+	protected void handleDispose(DisposeEvent event) {
+		if (model != null && !model.isDisposed()) {
+			model.dispose();
+		}
+		super.handleDispose(event);
+	}
+	
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object)
+	 */
+	protected void internalRefresh(Object element) {
+		if ( getInput() == null ) return;
+		if (element == getInput() )
+			getFactory().refreshGraph(getModel());
+		else
+			getFactory().refresh(getModel(), element);
+	}
+
+	protected void doUpdateItem(Widget item, Object element, boolean fullMap) {
+		if (item == getModel()) {
+			getFactory().update(getModel().getNodesArray());
+			getFactory().update(getModel().getConnectionsArray());
+		} else if (item instanceof IGraphItem) {
+			getFactory().update((IGraphItem) item);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object)
+	 */
+	protected Widget doFindInputItem(Object element) {
+		if (element == getInput())
+			return getModel();
+		return null;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object)
+	 */
+	protected Widget doFindItem(Object element) {
+		Widget node = (GraphItem) getModel().getNodesMap().get(element);
+		Widget connection = (GraphItem) getModel().getConnectionMap().get(
+				element);
+		return (node != null) ? node : connection;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.StructuredViewer#getSelectionFromWidget()
+	 */
+	protected List getSelectionFromWidget() {
+		List internalSelection = getWidgetSelection();
+		LinkedList externalSelection = new LinkedList();
+		for (Iterator i = internalSelection.iterator(); i.hasNext();) {
+			// @tag zest.todo : should there be a method on IGraphItem to get
+			// the external data?
+			IGraphItem item = (IGraphItem) i.next();
+			if (item instanceof IGraphModelNode) {
+				externalSelection.add(((IGraphModelNode) item)
+						.getExternalNode());
+			} else if (item instanceof IGraphModelConnection) {
+				externalSelection.add(((IGraphModelConnection) item)
+						.getExternalConnection());
+			} else if (item instanceof Widget) {
+				externalSelection.add(((Widget) item).getData());
+			}
+		}
+		return externalSelection;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.StructuredViewer#setSelectionToWidget(java.util.List,
+	 *      boolean)
+	 */
+	protected void setSelectionToWidget(List l, boolean reveal) {
+		EditPartViewer viewer = getEditPartViewer();
+		List selection = new LinkedList();
+		for (Iterator i = l.iterator(); i.hasNext();) {
+			Object obj = i.next();
+			IGraphModelNode node = getModel().getInternalNode(obj);
+			IGraphModelConnection conn = getModel().getInternalConnection(obj);
+			if (node != null) {
+				selection.add(node);
+			}
+			if (conn != null) {
+				selection.add(conn);
+			}
+		}
+		viewer.setSelection(new StructuredSelection(selection));
+	}
+
+	/**
+	 * Gets the internal model elements that are selected.
+	 * 
+	 * @return
+	 */
+	protected List getWidgetSelection() {
+		List editParts = getEditPartViewer().getSelectedEditParts();
+		List modelElements = new ArrayList();
+		for (Iterator i = editParts.iterator(); i.hasNext();) {
+			EditPart part = (EditPart) i.next();
+			if (part.getModel() instanceof Widget)
+				modelElements.add(part.getModel());
+		}
+		return modelElements;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object,
+	 *      java.lang.Object)
+	 */
+	protected void inputChanged(Object input, Object oldInput) {
+		IStylingGraphModelFactory factory = getFactory();
+		factory.setConnectionStyle(getConnectionStyle());
+		factory.setNodeStyle(getNodeStyle());
+		GraphModel newModel = factory.createGraphModel();
+		// get current list of nodes before they are re-created from the
+		// factory & content provider
+		Map oldNodesMap = (model != null ? model.getNodesMap()
+				: Collections.EMPTY_MAP);
+
+		if (model != null && !model.isDisposed()) {
+			// Dispose the model
+			model.dispose();
+		}
+		
+		model = newModel;
+		model.setNodeStyle(getNodeStyle());
+		model.setConnectionStyle(getConnectionStyle());
+
+		// check if any of the pre-existing nodes are still present
+		// in this case we want them to keep the same location & size
+		for (Iterator iter = oldNodesMap.keySet().iterator(); iter.hasNext();) {
+			Object data = iter.next();
+			IGraphModelNode newNode = model.getInternalNode(data);
+			if (newNode != null) {
+				IGraphModelNode oldNode = (IGraphModelNode) oldNodesMap
+						.get(data);
+				newNode.setPreferredLocation(oldNode.getXInLayout(), oldNode
+						.getYInLayout());
+				newNode.setSizeInLayout(oldNode.getWidthInLayout(), oldNode
+						.getHeightInLayout());
+			}
+		}
+		getEditPartViewer().setContents(model);
+		applyLayout();
+	}
+
+	/**
+	 * Returns the factory used to create the model. This must not be called
+	 * before the content provider is set.
+	 * 
+	 * @return
+	 */
+	protected abstract IStylingGraphModelFactory getFactory();
+
+	protected void filterVisuals() {
+		if (getModel() == null)
+			return;
+		Object[] filtered = getFilteredChildren(getInput());
+		SimpleGraphComparator comparator = new SimpleGraphComparator();
+		TreeSet filteredElements = new TreeSet(comparator);
+		TreeSet unfilteredElements = new TreeSet(comparator);
+		List connections = getModel().getConnections();
+		List nodes = getModel().getNodes();
+		if (filtered.length == 0) {
+			// set everything to invisible.
+			// @tag zest.bug.156528-Filters.check : should we only filter out
+			// the nodes?
+			for (Iterator i = connections.iterator(); i.hasNext();) {
+				IGraphModelConnection c = (IGraphModelConnection) i.next();
+				c.setVisible(false);
+			}
+			for (Iterator i = nodes.iterator(); i.hasNext();) {
+				IGraphModelNode n = (IGraphModelNode) i.next();
+				n.setVisible(false);
+			}
+			return;
+		}
+		for (Iterator i = connections.iterator(); i.hasNext();) {
+			IGraphModelConnection c = (IGraphModelConnection) i.next();
+			if (c.getExternalConnection() != null)
+				unfilteredElements.add(c);
+		}
+		for (Iterator i = nodes.iterator(); i.hasNext();) {
+			IGraphModelNode n = (IGraphModelNode) i.next();
+			if (n.getExternalNode() != null)
+				unfilteredElements.add(n);
+		}
+		for (int i = 0; i < filtered.length; i++) {
+			Object modelElement = getModel().getInternalConnection(filtered[i]);
+			if (modelElement == null) {
+				modelElement = getModel().getInternalNode(filtered[i]);
+			}
+			if (modelElement != null) {
+				filteredElements.add(modelElement);
+			}
+		}
+		unfilteredElements.removeAll(filteredElements);
+		// set all the elements that did not pass the filters to invisible, and
+		// all the elements that passed to visible.
+		while (unfilteredElements.size() > 0) {
+			IGraphItem i = (IGraphItem) unfilteredElements.first();
+			i.setVisible(false);
+			unfilteredElements.remove(i);
+		}
+		while (filteredElements.size() > 0) {
+			IGraphItem i = (IGraphItem) filteredElements.first();
+			i.setVisible(true);
+			filteredElements.remove(i);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.StructuredViewer#getRawChildren(java.lang.Object)
+	 */
+	protected Object[] getRawChildren(Object parent) {
+		if (parent == getInput()) {
+			// get the children from the model.
+			LinkedList children = new LinkedList();
+			if (getModel() != null) {
+				List connections = getModel().getConnections();
+				List nodes = getModel().getNodes();
+				for (Iterator i = connections.iterator(); i.hasNext();) {
+					IGraphModelConnection c = (IGraphModelConnection) i.next();
+					if (c.getExternalConnection() != null) {
+						children.add(c.getExternalConnection());
+					}
+				}
+				for (Iterator i = nodes.iterator(); i.hasNext();) {
+					IGraphModelNode n = (IGraphModelNode) i.next();
+					if (n.getExternalNode() != null) {
+						children.add(n.getExternalNode());
+					}
+				}
+				return children.toArray();
+			}
+		}
+		return super.getRawChildren(parent);
+	}
+	
+
+	/**
+	 * 
+	 */
+	public void reveal(Object element) {
+		Widget[] items = this.findItems(element);
+		for (int i = 0; i < items.length; i++) {
+			Widget item = items[i];
+			if ( item instanceof GraphModelNode ) {
+				GraphModelNode graphModelNode = (GraphModelNode) item;
+				graphModelNode.highlight();
+			}
+			else if ( item instanceof GraphModelConnection ) {
+				GraphModelConnection graphModelConnection = (GraphModelConnection) item;
+				graphModelConnection.highlight();
+			}
+		}
+	}
+	
+	public void unReveal(Object element) {
+		Widget[] items = this.findItems(element);
+		for (int i = 0; i < items.length; i++) {
+			Widget item = items[i];
+			if ( item instanceof GraphModelNode ) {
+				GraphModelNode graphModelNode = (GraphModelNode) item;
+				graphModelNode.unhighlight();
+			}
+			else if ( item instanceof GraphModelConnection ) {
+				GraphModelConnection graphModelConnection = (GraphModelConnection) item;
+				graphModelConnection.unhighlight();
+			}
+		}		
+	}
+
+
+	/**
+	 * Applies the viewers layouts.
+	 * 
+	 */
+	public abstract void applyLayout();
+
+	/**
+	 * Returns the internal graph model.
+	 * 
+	 * @return the internal graph model.
+	 */
+	protected final GraphModel getModel() {
+		if (model == null)
+			createModel();
+		return model;
+	}
+
+	protected final GraphModel createModel() {
+		this.model = getFactory().createGraphModel();
+		return model;
+	}
+
+	/**
+	 * Returns the underlying editpart viewer for this viewer.
+	 * 
+	 * @return the underlying editpart viewer for this viewer.
+	 */
+	protected abstract EditPartViewer getEditPartViewer();
+
+	/**
+	 * Removes the given connection object from the layout algorithm and the
+	 * model.
+	 * 
+	 * @param connection
+	 */
+	public void removeRelationship(Object connection) {
+		IGraphModelConnection relation = model
+				.getInternalConnection(connection);
+
+		if (relation != null) {
+			// remove the relationship from the layout algorithm
+			if (getLayoutAlgorithm() != null)
+				getLayoutAlgorithm().removeRelationship(relation);
+			// remove the relationship from the model
+			getModel().removeConnection(relation);
+			applyLayout();
+		}
+	}
+
+	/**
+	 * Creates a new node and adds it to the graph. If it already exists nothing
+	 * happens.
+	 * 
+	 * @param newNode
+	 */
+	public void addNode(Object element) {
+		if (model.getInternalNode(element) == null) {
+			// create the new node
+			IGraphModelNode newNode = getFactory().createNode(model, element);
+
+			// add it to the layout algorithm
+			if (getLayoutAlgorithm() != null)
+				getLayoutAlgorithm().addEntity(newNode);
+			applyLayout();
+		}
+	}
+
+	/**
+	 * Removes the given element from the layout algorithm and the model.
+	 * 
+	 * @param element
+	 *            The node element to remove.
+	 */
+	public void removeNode(Object element) {
+		IGraphModelNode node = model.getInternalNode(element);
+
+		if (node != null) {
+			// remove the node from the layout algorithm and all the connections
+			if (getLayoutAlgorithm() != null) {
+				getLayoutAlgorithm().removeEntity(node);
+				getLayoutAlgorithm().removeRelationships(
+						node.getSourceConnections());
+				getLayoutAlgorithm().removeRelationships(
+						node.getTargetConnections());
+			}
+
+			// remove the node and it's connections from the model
+			getModel().removeNode(node);
+			applyLayout();
+		}
+	}
+
+	/**
+	 * Creates a new relationship between the source node and the destination
+	 * node. If either node doesn't exist then it will be created.
+	 * 
+	 * @param connection
+	 *            The connection data object.
+	 * @param srcNode
+	 *            The source node data object.
+	 * @param destNode
+	 *            The destination node data object.
+	 */
+	public void addRelationship(Object connection, Object srcNode,
+			Object destNode) {
+		// create the new relationship
+		IStylingGraphModelFactory modelFactory = getFactory();
+		IGraphModelConnection newConnection = modelFactory.createConnection(
+				model, connection, srcNode, destNode);
+
+		// add it to the layout algorithm
+		if (getLayoutAlgorithm() != null)
+			getLayoutAlgorithm().addRelationship(newConnection);
+		applyLayout();
+	}
+
+	/**
+	 * Adds a new relationship given the connection. It will use the content
+	 * provider to determine the source and destination nodes.
+	 * 
+	 * @param connection
+	 *            The connection data object.
+	 */
+	public void addRelationship(Object connection) {
+		IStylingGraphModelFactory modelFactory = getFactory();
+		if (model.getInternalConnection(connection) == null) {
+			if (modelFactory.getContentProvider() instanceof IGraphContentProvider) {
+				IGraphContentProvider content = ((IGraphContentProvider) modelFactory
+						.getContentProvider());
+				Object source = content.getSource(connection);
+				Object dest = content.getDestination(connection);
+				// create the new relationship
+				IGraphModelConnection newConnection = modelFactory
+						.createConnection(model, connection, source, dest);
+				// add it to the layout algorithm
+				if (getLayoutAlgorithm() != null)
+					getLayoutAlgorithm().addRelationship(newConnection);
+			} else {
+				throw new UnsupportedOperationException();
+			}
+		}
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/AbstractZoomableViewer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/AbstractZoomableViewer.java
new file mode 100644
index 0000000..0e5d650
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/AbstractZoomableViewer.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.editparts.ZoomManager;
+import org.eclipse.jface.viewers.StructuredViewer;
+
+/**
+ * A simple interface that provides zooming capabilites. Not intended to be subclassed by clients.
+ * @author Del Myers
+ *
+ */
+//@tag bug.156286-Zooming.fix
+public abstract class AbstractZoomableViewer extends StructuredViewer {
+	/**
+	 * Returns a ZoomManager that zooming can be done on. May return null if none
+	 * is available.
+	 * @return a ZoomManager that zooming can be done on.
+	 */
+	protected abstract ZoomManager getZoomManager();
+	
+	public void zoomTo(int x, int y, int width, int height) {
+		Rectangle r = new Rectangle(x,y,width,height);
+		if (r.isEmpty()) {
+			getZoomManager().setZoomAsText("100%");
+		} else {
+			getZoomManager().zoomTo(r);
+		}
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/DAGViewer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/DAGViewer.java
new file mode 100644
index 0000000..1ea643f
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/DAGViewer.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.mylar.zest.core.internal.treegraphviewer.DagViewerImpl;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * 
+ * @author Ian Bull
+ *
+ */
+public class DAGViewer extends StructuredViewer {
+
+	DagViewerImpl viewer = null;
+
+	public DAGViewer(Composite composite, int style) {
+		this.viewer = new DagViewerImpl(composite, style);
+	}
+	
+	
+	protected void inputChanged(Object input, Object oldInput) {
+		IDAGContentProvider contentProvider = (IDAGContentProvider) getContentProvider();
+		contentProvider.inputChanged(this, oldInput, input);
+		ILabelProvider labelProvider = (ILabelProvider)getLabelProvider();
+		this.viewer.setContents(input, contentProvider, labelProvider);
+	}
+	
+	protected Widget doFindInputItem(Object element) {
+		return null;
+	}
+
+	protected Widget doFindItem(Object element) {
+		return null;
+	}
+
+	protected void doUpdateItem(Widget item, Object element, boolean fullMap) {
+
+	}
+
+	protected List getSelectionFromWidget() {
+		return Collections.EMPTY_LIST;
+	}
+
+	protected void internalRefresh(Object element) {
+
+	}
+
+	public void reveal(Object element) {
+
+	}
+
+	protected void setSelectionToWidget(List l, boolean reveal) {
+
+	}
+
+	public Control getControl() {
+		return viewer;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/EntityConnectionData.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/EntityConnectionData.java
new file mode 100644
index 0000000..f79f5b6
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/EntityConnectionData.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+/**
+ * A simple object that is used as the "external connection" in content providers that don't
+ * ask the user to create their own external connection. 
+ * 
+ * This is used whenever users don't specify a connection
+ * 
+ * @author Del Myers
+ */
+public final class EntityConnectionData {
+	public final Object source;
+	public final Object dest;
+	
+	
+	/**
+	 * Creates a new entity connection data.  The source and dest
+	 * are users nodes.
+	 */
+	public EntityConnectionData(Object source, Object dest) {
+		this.source = source;
+		this.dest = dest;
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#equals(java.lang.Object)
+	 */
+	public boolean equals(Object obj) {
+		if ( !(obj instanceof EntityConnectionData) ) return false;
+		EntityConnectionData that = (EntityConnectionData) obj;
+		return (this.source.equals(that.source) && this.dest.equals(that.dest));
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#hashCode()
+	 */
+	public int hashCode() {
+		return this.source.hashCode() + this.dest.hashCode();
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/GraphOverviewer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/GraphOverviewer.java
new file mode 100644
index 0000000..7cfb267
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/GraphOverviewer.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.mylar.zest.core.internal.graphviewer.overview.GraphOverviewerImpl;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.IPartService;
+import org.eclipse.ui.IWorkbenchPart;
+
+/**
+ * A viewer that can be used as an overview of graphs. It provides a small view that shows
+ * only rectangles representing the nodes of a graph that exists in the most recently selected
+ * workbench part that contains a graph. Does not show connections, and does not
+ * provide any selections or items. No interaction can be done directly through this viewer.
+ * @author Del Myers
+ *
+ */
+public class GraphOverviewer extends StructuredViewer implements DisposeListener {
+	private GraphOverviewerImpl viewer;
+	private AbstractZoomableViewer currentHookedViewer;
+	private IPartService service;
+	private ZoomablePartListener partListener;
+	private class ZoomablePartListener implements IPartListener {
+		public void partActivated(IWorkbenchPart part) {
+			if (part instanceof IZoomableWorkbenchPart) {
+				AbstractZoomableViewer viewer = 
+					((IZoomableWorkbenchPart)part).getZoomableViewer();
+				if (viewer != currentHookedViewer && viewer instanceof AbstractStructuredGraphViewer) {
+					GraphOverviewer.this.hookViewer((AbstractStructuredGraphViewer) viewer);
+				}
+			}
+		}
+		public void partDeactivated(IWorkbenchPart part) {
+
+		}
+	
+		public void partBroughtToTop(IWorkbenchPart part) {
+			if (part instanceof IZoomableWorkbenchPart) {
+				AbstractZoomableViewer viewer = 
+					((IZoomableWorkbenchPart)part).getZoomableViewer();
+				if (viewer != currentHookedViewer) {
+					GraphOverviewer.this.unhookViewer();
+				}
+			}
+		}
+		public void partClosed(IWorkbenchPart part) {
+			if (part instanceof IZoomableWorkbenchPart) {
+				AbstractZoomableViewer viewer = 
+					((IZoomableWorkbenchPart)part).getZoomableViewer();
+				if (viewer == currentHookedViewer) {
+					GraphOverviewer.this.unhookViewer();
+				}
+			}
+		}
+		
+		public void partOpened(IWorkbenchPart part) {}
+		
+	}
+	
+	/**
+	 * 
+	 */
+	public GraphOverviewer(Composite parent, IPartService service) {
+		this.viewer = new GraphOverviewerImpl();
+		viewer.createControl(parent);
+		this.service = service;
+		partListener = new ZoomablePartListener();
+		service.addPartListener(partListener);
+		parent.addDisposeListener(this);
+	}
+	
+	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object)
+	 */
+	protected Widget doFindInputItem(Object element) {
+		return null;
+	}
+
+	/**
+	 * Hooks this viewer to the given structured graph viewer. This need not be called by clients,
+	 * as it is autmatically updated based on selections. 
+	 * @param zoomViewer the viewer to hook to.
+	 */
+	protected void hookViewer(AbstractStructuredGraphViewer zoomViewer) {
+		viewer.setContents(zoomViewer.getEditPartViewer());
+		currentHookedViewer = zoomViewer;
+	}
+
+	/**
+	 * Unhooks the currently hooked viewer.
+	 */
+	protected void unhookViewer() {
+		//viewer.unhookViewer();		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object)
+	 */
+	protected Widget doFindItem(Object element) {
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.StructuredViewer#doUpdateItem(org.eclipse.swt.widgets.Widget, java.lang.Object, boolean)
+	 */
+	protected void doUpdateItem(Widget item, Object element, boolean fullMap) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.StructuredViewer#getSelectionFromWidget()
+	 */
+	protected List getSelectionFromWidget() {
+		return Collections.EMPTY_LIST;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object)
+	 */
+	protected void internalRefresh(Object element) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.StructuredViewer#reveal(java.lang.Object)
+	 */
+	public void reveal(Object element) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.StructuredViewer#setSelectionToWidget(java.util.List, boolean)
+	 */
+	protected void setSelectionToWidget(List l, boolean reveal) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.Viewer#getControl()
+	 */
+	public Control getControl() {
+		return viewer.getControl();
+	}
+
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
+	 */
+	public void widgetDisposed(DisposeEvent e) {
+		service.removePartListener(partListener);
+		partListener = null;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IConnectionStyleBezierExtension.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IConnectionStyleBezierExtension.java
new file mode 100644
index 0000000..1ceae65
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IConnectionStyleBezierExtension.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+/**
+ * An extension to the IConnectinStyleProvider that allows styling specific to
+ * bezier curves.
+ * 
+ * Bezier curves are defined by a set of four points: two point in the layout
+ * (start and end), and two related control points (also start and end). The
+ * control points are defined relative to their corresponding layout point.
+ * This definition includes an angle between the layout point and the line
+ * between the two layout points, as well as a ratio distance from the corresponding
+ * layout point. The ratio distance is defined as a fraction between 0 and 1
+ * of the distance between the two layout points. Using this definition
+ * allows bezier curves to have a consistant look regardless of the actual
+ * positions of the nodes in the layouts. 
+ * @author Del Myers
+ *
+ */
+//@tag bug(152530-Bezier(fix)) : users can style bezier curves.
+public interface IConnectionStyleBezierExtension {
+
+	/**
+	 * Gets the angle between the start point, and the line between the start 
+	 * and end, which will define the position of the start control point.
+	 * If the start angle, and the end angle are the same sign, the two control
+	 * points are guaranteed to be on the same side of the line.
+	 * @param rel the relationship to base on.
+	 * @return the start angle or <code>Double.NaN</code> for defaults.
+	 */
+	double getStartAngle(Object rel);
+	
+	/**
+	 * Gets the angle between the end point, and the line between the start 
+	 * and end, which will define the position of the end control point.
+	 * If the start angle, and the end angle are the same sign, the two control
+	 * points are guaranteed to be on the same side of the line.
+	 * @param rel the relationship to base on.
+	 * @return the end angle or <code>Double.NaN</code> for defaults.
+	 */
+	double getEndAngle(Object rel);
+	
+	/**
+	 * Gets the distance between the start point and the start control point,
+	 * as a fraction of the distance between the start point and end point.
+	 * @param rel the relationship to base on.
+	 * @return the start distance or <code>Double.NaN</code> for defaults.
+	 */
+	double getStartDistance(Object rel);
+	
+	/**
+	 * Gets the distance between the end point and the end control point,
+	 * as a fraction of the distance between the start point and end point.
+	 * @param rel the relationship to base on.
+	 * @return the end distance or <code>Double.NaN</code> for defaults.
+	 */
+	double getEndDistance(Object rel);
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IConnectionStyleProvider.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IConnectionStyleProvider.java
new file mode 100644
index 0000000..fc4f6eb
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IConnectionStyleProvider.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.ui.services.IDisposable;
+
+/**
+ * An extension to label providers, to supply styles for connections based upon 
+ * relationships, rather than on connected nodes.
+ * @author Del Myers
+ * @see #IGraphContentProvider
+ * @see #IEntityStyleProvider
+ *
+ */
+//@tag bug(151327-Styles) : created to solve this bug
+public interface IConnectionStyleProvider extends IDisposable {
+	/**
+	 * Returns the style flags for this connection. Valid flags are those
+	 * that begin with CONNECTION in @see org.eclipse.mylar.zest.core.ZestStyles. Check
+	 * ZestStyles for legal combinations.
+	 * @param rel the relationship represented by this connection.
+	 * @return the style flags for this connection.
+	 * @see org.eclipse.mylar.zest.core.ZestStyles
+	 */
+	public int getConnectionStyle(Object rel);
+	
+	/**
+	 * Returns the color for the connection. Null for default.  Any resources created by this class must be disposed by
+	 * this class.
+	 * @param rel the relationship represented by this connection.
+	 * @return the color.
+	 * @see #dispose()
+	 */
+	public Color getColor(Object rel);
+	
+	/**
+	 * Returns the highlighted color for this connection. Null for default.  Any resources created by this class must be disposed by
+	 * this class.
+	 * @param rel the relationship represented by this connection.
+	 * @return the highlighted color. Null for default.
+	 * @see #dispose()
+	 */
+	public Color getHighlightColor(Object rel);
+	
+	/**
+	 * Returns the line width of the connection. -1 for default.
+	 * @param rel the relationship represented by this connection.
+	 * @return the line width for the connection. -1 for default.
+	 */
+	public int getLineWidth(Object rel);
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IDAGContentProvider.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IDAGContentProvider.java
new file mode 100644
index 0000000..43ee799
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IDAGContentProvider.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+
+/**
+ * 
+ * @author Ian Bull
+ */
+public interface IDAGContentProvider extends IStructuredContentProvider {
+	
+	
+	public boolean hasAdjacent( Object element );
+	
+	public Object[] getAdjacent( Object element );
+	
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IEntityConnectionStyleBezierExtension.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IEntityConnectionStyleBezierExtension.java
new file mode 100644
index 0000000..6b573b0
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IEntityConnectionStyleBezierExtension.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+/**
+ * An extension to the IEntityConnectinStyleProvider that allows styling specific to
+ * bezier curves.
+ * 
+ * Bezier curves are defined by a set of four points: two point in the layout
+ * (start and end), and two related control points (also start and end). The
+ * control points are defined relative to their corresponding layout point.
+ * This definition includes an angle between the layout point and the line
+ * between the two layout points, as well as a ratio distance from the corresponding
+ * layout point. The ratio distance is defined as a fraction between 0 and 1
+ * of the distance between the two layout points. Using this definition
+ * allows bezier curves to have a consistant look regardless of the actual
+ * positions of the nodes in the layouts. 
+ * @author Del Myers
+ *
+ */
+//@tag zest(bug(152530-Bezier(fix))) : users can style bezier curves.
+public interface IEntityConnectionStyleBezierExtension {
+
+	/**
+	 * Gets the angle between the start point, and the line between the start 
+	 * and end, which will define the position of the start control point.
+	 * If the start angle, and the end angle are the same sign, the two control
+	 * points are guaranteed to be on the same side of the line.
+	 * @param source the source node to base on.
+	 * @param dest the destination node to base on.
+	 * @return the start angle or <code>Double.NaN</code> for defaults.
+	 */
+	double getStartAngle(Object source, Object dest);
+
+	/**
+	 * Gets the angle between the end point, and the line between the start 
+	 * and end, which will define the position of the end control point.
+	 * If the start angle, and the end angle are the same sign, the two control
+	 * points are guaranteed to be on the same side of the line.
+	 * @param source the source node to base on.
+	 * @param dest the destination node to base on.
+	 * @return the end angle or <code>Double.NaN</code> for defaults.
+	 */
+	double getEndAngle(Object source, Object dest);
+
+	/**
+	 * Gets the distance between the start point and the start control point,
+	 * as a fraction of the distance between the start point and end point.
+	 * @param source the source node to base on.
+	 * @param dest the destination node to base on.
+	 * @return the start distance or <code>Double.NaN</code> for defaults.
+	 */
+	double getStartDistance(Object source, Object dest);
+
+	/**
+	 * Gets the distance between the end point and the end control point,
+	 * as a fraction of the distance between the start point and end point.
+	 * @param source the source node to base on.
+	 * @param dest the destination node to base on.
+	 * @return the end distance or <code>Double.NaN</code> for defaults.
+	 */
+	double getEndDistance(Object source, Object dest);
+}
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IEntityConnectionStyleProvider.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IEntityConnectionStyleProvider.java
new file mode 100644
index 0000000..4fb8c9a
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IEntityConnectionStyleProvider.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.ui.services.IDisposable;
+
+/**
+ * An extension for label providers which allows users to set styles for connections
+ * that are based on entity end points.
+ * @author Del Myers
+ *
+ */
+//@tag bug(151327-Styles) : fix
+public interface IEntityConnectionStyleProvider extends IDisposable {
+
+	/**
+	 * Returns the style flags for this connection. Valid flags are those
+	 * that begin with CONNECTION in @see org.eclipse.mylar.zest.core.ZestStyles. Check
+	 * ZestStyles for legal combinations.
+	 * @param src the source entity.
+	 * @param dest the destination entity.
+	 * @return the style flags for this connection.
+	 * @see org.eclipse.mylar.zest.core.ZestStyles
+	 */
+	public int getConnectionStyle(Object src, Object dest);
+	
+	/**
+	 * Returns the color for the connection. Null for default.
+	 * @param src the source entity.  Any resources created by this class must be disposed by
+	 * this class.
+	 * @param dest the destination entity.
+	 * @return the color.
+	 * @see #dispose()
+	 */
+	public Color getColor(Object src, Object dest);
+	
+	/**
+	 * Returns the highlighted color for this connection. Null for default.
+	 * @param src the source entity.  Any resources created by this class must be disposed by
+	 * this class.
+	 * @param dest the destination entity.
+	 * @return the highlighted color. Null for default.
+	 * @see #dispose()
+	 */
+	public Color getHighlightColor(Object src, Object dest);
+	
+	/**
+	 * Returns the line width of the connection. -1 for default.
+	 * @param src the source entity.
+	 * @param dest the destination entity.
+	 * @return the line width for the connection. -1 for default.
+	 */
+	public int getLineWidth(Object src, Object dest);
+		
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IEntityStyleProvider.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IEntityStyleProvider.java
new file mode 100644
index 0000000..adec1c8
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IEntityStyleProvider.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.ui.services.IDisposable;
+
+/**
+ * An extension to Label providers for graphs. Gets specific details about the style of an
+ * entity before it is created. This style provider offers:
+ * 
+ * -Background and forground colours
+ * -Hilighted and unhighlighted colours (colours defined by selections).
+ * -Border color.
+ * -Highlighted and unhighlighted colours for borders.
+ * -Border width
+ * -Font for text inside the entity.
+ * 
+ * Any method may return null if the Zest defaults are preferred.
+ * 
+ * NOTE: It is up to the implementors of this interface to dispose of any Colors or Fonts
+ * that are created by this class. The dispose() method will be called at the end of the
+ * entity's life-cycle so that this class may dispose of its resources.
+ * 
+ * @author Del Myers
+ * @see org.eclipse.jface.viewers.IColorProvider
+ * @tag bug(151327-Styles) : created to solve this bug
+ */
+public interface IEntityStyleProvider extends IDisposable {
+
+	/**
+	 * Returns the forground colour of this entity. May return null
+	 * for defaults. Any resources created by this class must be disposed by
+	 * this class.
+	 * @param entity the entity to be styled.
+	 * @return the forground colour of this entity.
+	 * @see #dispose()
+	 */
+	public Color getHighlightColor(Object entity);
+
+	/**
+	 * Returns the background colour for this entity. May return null
+	 * for defaults. Any resources created by this class must be disposed by
+	 * this class.
+	 * @param entity the entity to be styled.
+	 * @return the background colour for this entity.
+	 * @see #dispose()
+	 */
+	public Color getBorderColor(Object entity);
+	/**
+	 * Returns the border highlight colour for this entity. May return null
+	 * for defaults. Any resources created by this class must be disposed by
+	 * this class.
+	 * @param entity the entity to be styled.
+	 * @return the border highlight colour for this entity.
+	 * @see #dispose()
+	 */
+	public Color getBorderHighlightColor(Object entity);
+	
+	/**
+	 * Returns the border width for this entity. May return -1 for defaults.
+	 * @param entity the entity to be styled.
+	 * @return the border width, or -1 for defaults.
+	 */
+	public int getBorderWidth(Object entity);
+		
+	/**
+	 * Returns true iff the adjacent entities should be highlighted when this 
+	 * node is selected. Zest's default action is true.
+	 * @return true iff the adjacent entities should be highlighted when this 
+	 * node is selected.
+	 */
+	public boolean highlightAdjacentEntities(Object entity);
+	
+	/**
+	 * Returns the color that adjacent entities will be drawn when this entity
+	 * is selected. Will be ignored if HighlightAdjacentEntities() returns false.
+	 * May return null for defaults. Any resources created by this class must be disposed by
+	 * this class.
+	 * @param entity the entity to be styled.
+	 * @return  the color for adjacent entities.
+	 * @see #highlightAdjacentEntities(Object entity)
+	 * @see #dispose()
+	 */
+	public Color getAdjacentEntityHighlightColor(Object entity);
+	
+	
+	/**
+	 * Returns the colour that this node should be coloured.  This will be ignored 
+	 * if getNodeColour returns null.  Any resources created by this class must be diposed by
+	 * this class.
+	 * @param entity The entity to be styled
+	 * @return The colour for the node
+	 * @see #dispose()
+	 */
+	public Color getBackgroundColour(Object entity);
+	
+	
+	public Color getForegroundColour(Object entity);
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IGraphContentProvider.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IGraphContentProvider.java
new file mode 100644
index 0000000..6046923
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IGraphContentProvider.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+
+/**
+ * A graph content provider. 
+ * 
+ * @author Ian Bull
+ */
+public interface IGraphContentProvider extends IStructuredContentProvider {
+
+	
+	
+	/**
+	 * Gets the source Object for the given relationship. Note, at least one of the source
+	 * or destination must not be null. If both are null, then nothing can be displayed in
+	 * the graph (a relationship cannot exist without nodes to be connected to). However,
+	 * if one of getSource() or getDestination() returns null, then the resulting graph will
+	 * contain an unconnected node for the non-null object returned from the other method.
+	 * @param rel the relationship.
+	 * @return the source, or null for an unconnected destination.
+	 */
+	public Object getSource( Object rel );
+	
+	/**
+	 * Gets the target Object for the given relationship. Note, at least one of the source
+	 * or destination must not be null. If both are null, then nothing can be displayed in
+	 * the graph (a relationship cannot exist without nodes to be connected to). However,
+	 * if one of getSource() or getDestination() returns null, then the resulting graph will
+	 * contain an unconnected node for the non-null object returned from the other method.
+	 * @param rel the relationship.
+	 * @return the destination, or null for an unconnected source.
+	 */
+	public Object getDestination( Object rel );
+	
+	/**
+	 * Returns all the relationships in the graph for the given input.
+	 * @input the input model object.
+	 * @return all the relationships in the graph for the given input.
+	 */
+	public Object[] getElements(Object input);
+
+	/**
+	 * Gets the weight of an edge given the connection object.  The weight will be either -1 or 
+	 * a double between 0.0 and 1.0
+	 * @param connection	The connection data object.
+	 * @return double
+	 */
+	public double getWeight(Object connection);
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IGraphEntityContentProvider.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IGraphEntityContentProvider.java
new file mode 100644
index 0000000..b98b458
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IGraphEntityContentProvider.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+/**
+ * 
+ * @author Ian Bull
+ *
+ */
+public interface IGraphEntityContentProvider extends IStructuredContentProvider {
+	
+	public Object[] getElements(Object inputElement);
+	
+	/**
+	 * Gets the elements this object is connected to
+	 * @param entity
+	 * @return
+	 */
+	public Object[] getConnectedTo( Object entity );
+	
+	public double getWeight( Object entity1, Object entity2 );
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IGraphEntityRelationshipContentProvider.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IGraphEntityRelationshipContentProvider.java
new file mode 100644
index 0000000..b5fb2dd
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IGraphEntityRelationshipContentProvider.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+
+/**
+ * A content provider that is node-relationship centric. Call-backs return model
+ * nodes to the user, and ask for relationships. Both nodes and relationships are
+ * represented by the user's model.
+ * @author Del Myers
+ *
+ */
+//@tag bug.154580-Content.fix : new content provider that returns relationships for the given source and destination.
+public interface IGraphEntityRelationshipContentProvider  extends IStructuredContentProvider{
+	/**
+	 * Gets the relationships between the given source and destination nodes.
+	 * @param source the source node.
+	 * @param dest the destination node.
+	 * @return objects represtenting the different relationships between the nodes.
+	 */
+	public Object[] getRelationships(Object source, Object dest);
+	
+	/**
+	 * Gets the weight for the given relationship.
+	 * @param rel the relationship.
+	 * @return the weight.
+	 */
+	public int getWeight(Object rel);
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/INestedGraphContentProvider.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/INestedGraphContentProvider.java
new file mode 100644
index 0000000..ae25aef
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/INestedGraphContentProvider.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+/**
+ * Extends {@link org.eclipse.mylar.zest.core.viewers.IGraphContentProvider} to provide methods
+ * for getting the parent and children nodes.
+ * 
+ * @author Chris Callendar
+ */
+public interface INestedGraphContentProvider extends IGraphContentProvider {
+
+	/**
+	 * Gets the parent for the given node.
+	 * @param node	The node object.
+	 * @return The parent object.
+	 */
+	public Object getParent(Object node);
+	
+	/**
+	 * Gets the children for the given node.
+	 * @param node	The node object.
+	 * @return An array of the children objects.
+	 */
+	public Object[] getChildren(Object node);
+	
+	/**
+	 * Returns if there are children for the given node.
+	 * @param node the node in question
+	 * @return boolean if the node has children
+	 */
+	public boolean hasChildren(Object node);
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/INestedGraphEntityContentProvider.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/INestedGraphEntityContentProvider.java
new file mode 100644
index 0000000..900493d
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/INestedGraphEntityContentProvider.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+
+/**
+ * Extends {@link org.eclipse.mylar.zest.core.viewers.IGraphEntityContentProvider} to provide methods
+ * for getting the parent and children nodes.
+ * 
+ * @author Chris Callendar
+ */
+public interface INestedGraphEntityContentProvider extends IGraphEntityContentProvider, ITreeContentProvider {
+
+	/**
+	 * Gets the parent for the given node.
+	 * @param node	The node object.
+	 * @return The parent object.
+	 */
+	public Object getParent(Object node);
+	
+	/**
+	 * Gets the children for the given node.
+	 * @param node	The node object.
+	 * @return An array of the children objects.
+	 */
+	public Object[] getChildren(Object node);
+	
+	/**
+	 * Returns if there are children for the given node.
+	 * @param node the node in question
+	 * @return boolean if the node has children
+	 */
+	public boolean hasChildren(Object node);
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/INestedGraphFocusChangedListener.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/INestedGraphFocusChangedListener.java
new file mode 100644
index 0000000..2ee2f2f
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/INestedGraphFocusChangedListener.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+/**
+ * A listener for when focus (root-level) nodes change in a nested graph viewer.
+ * @author Del Myers
+ *
+ */
+//@tag bug(151889-ViewCoupling)
+public interface INestedGraphFocusChangedListener {
+
+	/**
+	 * Signals that focus (root-level) nodes change in a nested graph viewer.
+	 * If either of the nodes is set to null, the client can assume the top-level
+	 * of the nested graph.
+	 * @param oldNode the old node of focus.
+	 * @param newNode the new node of focus.
+	 */
+	public void focusChanged(Object oldNode, Object newNode);
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/ITreeGraphContentProvider.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/ITreeGraphContentProvider.java
new file mode 100644
index 0000000..d3c8f60
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/ITreeGraphContentProvider.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+
+/**
+ * @author Ian Bull
+ */
+public interface ITreeGraphContentProvider extends IStructuredContentProvider, ITreeContentProvider, IGraphEntityContentProvider {
+
+	
+	public Object[] getGraphElements( Object inputElement );
+	
+	public Object[] getChildren( Object element );
+	
+	public Object[] getConnectedTo( Object element );
+	
+	public Object[] getEdge( Object element1, Object element2 );
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IZoomableWorkbenchPart.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IZoomableWorkbenchPart.java
new file mode 100644
index 0000000..751c0be
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/IZoomableWorkbenchPart.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+/**
+ * An interface that can be added to IWorkbenchParts based on ZEST views so that zooming
+ * is supported.
+ * @author Del Myers
+ *
+ */
+//@tag bug.156286-Zooming.fix : experimental
+public interface IZoomableWorkbenchPart {
+	/**
+	 * Returns the viewer that is zoomable.
+	 * @return the viewer that is zoomable.
+	 */
+	AbstractZoomableViewer getZoomableViewer();
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/NestedGraphViewer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/NestedGraphViewer.java
new file mode 100644
index 0000000..459ffd0
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/NestedGraphViewer.java
@@ -0,0 +1,513 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.editparts.ZoomManager;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModelEntityFactory;
+import org.eclipse.mylar.zest.core.internal.graphmodel.nested.NestedGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.NestedGraphViewerImpl;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts.NestedGraphEditPart;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts.NestedGraphNodeEditPart;
+import org.eclipse.mylar.zest.core.internal.nestedgraphviewer.parts.NestedGraphRootEditPart;
+import org.eclipse.mylar.zest.layouts.LayoutAlgorithm;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.ControlListener;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * @author Ian Bull
+ */
+public class NestedGraphViewer extends AbstractStructuredGraphViewer implements IDoubleClickListener, ControlListener,
+		DisposeListener, PropertyChangeListener {
+
+	private Composite parent = null;
+
+	private NestedGraphViewerImpl viewer = null;
+
+	private IStylingGraphModelFactory modelFactory = null;
+
+	private List focusListeners;
+
+	// to prevent endless loop when setting selection in the two viewers
+	private boolean settingViewerSelection = false;
+
+	private boolean settingTreeSelection = false;
+
+	/**
+	 * Initializes the viewer with the given styles.
+	 * 
+	 * @param parent
+	 * @param style
+	 *            the styles (which also get passed to the viewer impl
+	 * @see ZestStyles#NO_OVERLAPPING_NODES
+	 * @see ZestStyles#NODES_HIGHLIGHT_ADJACENT
+	 * @see ZestStyles#NO_SCROLLBARS
+	 * @see ZestStyles#ZOOM_EXPAND
+	 * @see ZestStyles#ZOOM_FAKE
+	 * @see ZestStyles#ZOOM_REAL
+	 */
+	public NestedGraphViewer(Composite parent, int style) {
+		super(style);
+		this.parent = parent;
+		this.parent.addDisposeListener(this);
+
+		GridLayout layout = new GridLayout(1, true);
+		GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+		parent.setLayoutData(data);
+		layout.marginHeight = 2;
+		layout.marginWidth = 2;
+		parent.setLayout(layout);
+		parent.addControlListener(this);
+
+		this.viewer = new NestedGraphViewerImpl(parent, style  );
+		data = new GridData(SWT.FILL, SWT.FILL, true, true);
+		this.viewer.getControl().setLayoutData(data);
+
+		this.viewer.addSelectionChangedListener(new ISelectionChangedListener() {
+			public void selectionChanged(SelectionChangedEvent event) {
+				setSelectionToTreeViewer(event.getSelection(), true);
+			}
+		});
+
+		hookControl(this.viewer.getControl());
+
+		focusListeners = new LinkedList();
+	}
+
+	/**
+	 * Gets the styles for this structuredViewer
+	 * 
+	 * @return
+	 */
+	public int getStyle() {
+		return this.viewer.getStyle();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.ContentViewer#setContentProvider(org.eclipse.jface.viewers.IContentProvider)
+	 */
+	public void setContentProvider(IContentProvider contentProvider) {
+		if (contentProvider instanceof INestedGraphContentProvider) {
+			super.setContentProvider(contentProvider);
+		} else if (contentProvider instanceof INestedGraphEntityContentProvider) {
+			super.setContentProvider(contentProvider);
+		} else {
+			throw new IllegalArgumentException(
+					"Invalid content provider, only INestedGraphContentProvider and INestedGraphEntityContentProvider are supported.");
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.StructuredViewer#setLabelProvider(org.eclipse.jface.viewers.IBaseLabelProvider)
+	 */
+	public void setLabelProvider(IBaseLabelProvider labelProvider) {
+		super.setLabelProvider(labelProvider);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object,
+	 *      java.lang.Object)
+	 */
+	protected void inputChanged(Object input, Object oldInput) {
+		//boolean highlightAdjacentNodes = ZestStyles.checkStyle(viewer.getStyle(), ZestStyles.NODES_HIGHLIGHT_ADJACENT);
+
+		// // TODO - NestedGraphContentProvider
+		// if (getContentProvider() instanceof INestedGraphContentProvider) {
+		// modelFactory = new NestedGraphModelFactory(this,
+		// highlightAdjacentNodes);
+		// }
+		// else
+		NestedGraphModel model = (NestedGraphModel) createModel();
+		modelFactory.setNodeStyle(getNodeStyle());
+		modelFactory.setConnectionStyle(getConnectionStyle());
+		// DebugPrint.println("Input Is: " + input);
+		//@tag zest(bug(153348-NestedStyle(fix))) : add connection style and node style.
+		//@tag zest(bug(154412-ClearStatic(fix))) : the factory now returns a generic GraphModel so that this method can be abstracted into AbstractStylingModelFactory.
+		model = (NestedGraphModel)modelFactory.createGraphModel();
+		model.setNodeStyle(getNodeStyle());
+		model.setConnectionStyle(getConnectionStyle());
+		model.addPropertyChangeListener(this);
+
+		// sets the model contents
+		viewer.setContents(model);
+
+	}
+
+	protected NestedGraphViewerImpl getViewer() {
+		return viewer;
+	}
+
+
+	public void reveal(Object element) {
+		// TODO Auto-generated method stub
+
+	}
+
+	/**
+	 * Gets the selected model elements as a List.
+	 * 
+	 * @return List
+	 */
+	protected List getSelectionFromWidget() {
+		Widget[] items = viewer.getSelectedModelElements();
+		ArrayList list = new ArrayList(items.length);
+		for (int i = 0; i < items.length; i++) {
+			Widget item = items[i];
+			Object e = item.getData();
+			if (e != null)
+				list.add(e);
+		}
+		return list;
+	}
+
+	/**
+	 * Sets the selection to the viewer. The list contains the data objects
+	 * which are used to retrieve the NestedGraphModelNode elements. These in
+	 * turn are used to get the associated edit part.
+	 * 
+	 * @param list
+	 *            the list of objects to select
+	 */
+	protected void setSelectionToWidget(List list, boolean reveal) {
+		if (settingTreeSelection)
+			return;
+
+		if (list == null) {
+			viewer.setSelection(new StructuredSelection());
+			return;
+		}
+
+//		ArrayList editPartList = new ArrayList(list.size());
+//		for (int i = 0; i < list.size(); i++) {
+//			Object data = list.get(i);
+//			NestedGraphModelNode node = (NestedGraphModelNode) model.getInternalNode(data);
+//			EditPart editPart = (EditPart) viewer.getEditPartRegistry().get(node);
+//			if (editPart != null) {
+//				// ensure that all the parents are showing their children
+//				if (reveal && (node.getParent() != null)) {
+//					for (NestedGraphModelNode parentNode = node.getCastedParent(); parentNode != null; parentNode = parentNode
+//							.getCastedParent()) {
+//						parentNode.setChildrenVisible(true);
+//					}
+//				}
+//				editPartList.add(i, editPart);
+//			}
+//		}
+		settingViewerSelection = true;
+		//viewer.setSelection(new StructuredSelection(editPartList));
+		super.setSelectionToWidget(list, reveal);
+		settingViewerSelection = false;
+	}
+
+	/**
+	 * Sets the selection to the tree viewer. The list contains the
+	 * NestedGraphNodeEditPart objects. The NestedGraphModelNode objects are
+	 * gotten from the edit part and then the data object for the node is
+	 * retrieved and put in a StructuredSelection and passed to the TreeViewer.
+	 * 
+	 * @param list
+	 *            the list of objects to select
+	 */
+	protected void setSelectionToTreeViewer(ISelection selection, boolean reveal) {
+		if (settingViewerSelection)
+			return;
+
+		if (selection instanceof IStructuredSelection) {
+			List list = ((IStructuredSelection) selection).toList();
+			ArrayList treeList = new ArrayList(list.size());
+			for (int i = 0; i < list.size(); i++) {
+				Object obj = list.get(i);
+				Object data = null;
+				if (obj instanceof NestedGraphNodeEditPart) {
+					NestedGraphNodeEditPart editPart = (NestedGraphNodeEditPart) obj;
+					NestedGraphModelNode node = editPart.getCastedModel();
+					data = node.getData();
+				} else if (obj instanceof NestedGraphEditPart) {
+					NestedGraphEditPart editPart = (NestedGraphEditPart) obj;
+					NestedGraphModelNode node = editPart.getCastedModel().getCurrentNode();
+					data = node.getData();
+				}
+				if (data != null) {
+					treeList.add(data);
+				}
+			}
+			settingTreeSelection = true;
+			settingTreeSelection = false;
+		}
+	}
+
+	public Control getControl() {
+		return viewer.getControl();
+	}
+
+	// Control Listener methods
+	public void controlMoved(ControlEvent e) {
+	}
+
+	public void controlResized(ControlEvent e) {
+		((Composite) getControl()).layout(true, true);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(org.eclipse.jface.viewers.DoubleClickEvent)
+	 */
+	public void doubleClick(DoubleClickEvent event) {
+		ISelection selection = event.getSelection();
+		NestedGraphModel model = (NestedGraphModel) getModel();
+		if (!selection.isEmpty() && (selection instanceof IStructuredSelection)) {
+			List list = ((IStructuredSelection) selection).toList();
+			Object data = list.get(0);
+			NestedGraphModelNode node = (NestedGraphModelNode) model.getInternalNode(data);
+			if ((node != null) && (node.getChildren().size() > 0) && !node.equals(model.getCurrentNode())) {
+				model.setCurrentNode(node);
+				viewer.fireModelUpdate();
+			}
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
+	 */
+	public void widgetDisposed(DisposeEvent e) {
+		if ( focusListeners != null)
+			focusListeners.clear();
+	}
+
+	/**
+	 * This implementation ignores the run boolean.
+	 * @param algorithm
+	 * @param run ignored by this implementation.
+	 */
+	public void setLayoutAlgorithm(LayoutAlgorithm algorithm, boolean run) {
+		viewer.setLayoutAlgorithm(algorithm);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
+	 */
+	// @tag zest(bug(151889-ViewCoupling)) : use a listener to update UI elements that
+	// want to know about focus changes.
+	public void propertyChange(PropertyChangeEvent evt) {
+		NestedGraphModel model = (NestedGraphModel) getModel();
+		if (evt.getSource() == model) {
+			if (evt.getPropertyName().equals(GraphModel.NODE_FOCUS_PROP)) {
+				IGraphModelNode old = (IGraphModelNode) evt.getOldValue();
+				IGraphModelNode current = (IGraphModelNode) evt.getNewValue();
+				Object externOld = (old != null) ? old.getExternalNode() : null;
+				Object externCurrent = null;
+				if (current != model.getRootNode()) {
+					externCurrent = (current != null) ? current.getExternalNode() : null;
+				}
+				fireFocusChanged(externOld, externCurrent);
+			}
+		}
+	}
+
+	/**
+	 * Add a listener for when focus (root-level) nodes change in this viewer.
+	 * 
+	 * @param listener
+	 *            the listener to add.
+	 */
+	public void addFocusListener(INestedGraphFocusChangedListener listener) {
+		// @tag performance(synchronization) : consider a write-behind method if
+		// concurrent modifications happen from non-display thread changes in
+		// the model.
+		if (!focusListeners.contains(listener))
+			focusListeners.add(listener);
+	}
+
+	/**
+	 * Removes the given listener from the list of focus change listeners.
+	 * 
+	 * @param listener
+	 *            the listener to remove.
+	 */
+	public void removeFocusListener(INestedGraphFocusChangedListener listener) {
+		// @tag performance(synchronization) : consider a write-behind method if
+		// concurrent modifications happen from non-display thread changes in
+		// the model.
+		focusListeners.remove(listener);
+	}
+
+	private void fireFocusChanged(Object externOld, Object externCurrent) {
+		// @tag performance(synchronization) : consider a write-behind method if
+		// concurrent modifications happen from non-display thread changes in
+		// the model.
+		for (Iterator i = focusListeners.iterator(); i.hasNext();) {
+			((INestedGraphFocusChangedListener) i.next()).focusChanged(externOld, externCurrent);
+		}
+	}
+
+	/**
+	 * Move forward in graph view navigation.
+	 * 
+	 */
+	public void goForward() {
+		// the model supports it, so we may as well expose it.
+		viewer.goForward();
+	}
+
+	/**
+	 * Move backward in graph view navigation.
+	 * 
+	 */
+	public void goBackward() {
+		viewer.goBack();
+	}
+
+	/**
+	 * Move to the parent in graph view navigation.
+	 * 
+	 */
+	public void goUp() {
+		viewer.goUp();
+	}
+
+	/**
+	 * @return true iff the model can navigate forward.
+	 */
+	public boolean canGoBackward() {
+		NestedGraphModel model = (NestedGraphModel) getModel();
+		return model.hasBackNode();
+	}
+
+	/**
+	 * Sets the focus to the given node, if it exists in the model. If null is
+	 * supplied, the top-level node is set as the focus.
+	 * 
+	 * @param node
+	 *            the node to focus on.
+	 */
+	public void setFocus(Object node) {
+		NestedGraphModel model = (NestedGraphModel) getModel();
+		if (node == null) {
+			viewer.setCurrentNode(model.getRootNode());
+		} else {
+			viewer.setCurrentNode((NestedGraphModelNode) model.getInternalNode(node));
+		}
+	}
+
+	/**
+	 * Returns the current node of focus. If null is returned, the client can assume
+	 * the top-level node of the graph.
+	 * @return the current node of focus.
+	 */
+	public Object getFocus() {
+		NestedGraphModel model = (NestedGraphModel) getModel();
+		IGraphModelNode node = model.getCurrentNode();
+		if (node == model.getRootNode()) {
+			return null;
+		} else if (node != null) {
+			return node.getExternalNode();
+		}
+		return null;
+	}
+	/**
+	 * 
+	 * @return true iff the model can navigate backward.
+	 */
+	public boolean canGoForward() {
+		NestedGraphModel model = (NestedGraphModel) getModel();
+		return model.hasForwardNode();
+	}
+
+	/**
+	 * 
+	 * @return true iff the current focus node has a parent.
+	 */
+	public boolean focusHasParent() {
+		NestedGraphModel model = (NestedGraphModel) getModel();
+		return model.hasParentNode();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractZoomableViewer#getZoomManager()
+	 */
+	protected ZoomManager getZoomManager() {
+		return ((NestedGraphRootEditPart)viewer.getRootEditPart()).getZoomManager();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractStructuredGraphViewer#applyLayout()
+	 */
+	public void applyLayout() {
+		//do nothing. Nested viewers have internal layouts.
+		//@tag zest.check : should we actually layout the current node?
+	}
+
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractStructuredGraphViewer#getEditPartViewer()
+	 */
+	protected EditPartViewer getEditPartViewer() {
+		return viewer;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractStructuredGraphViewer#getFactory()
+	 */
+	protected IStylingGraphModelFactory getFactory() {
+		if (modelFactory == null) {
+			modelFactory = new NestedGraphModelEntityFactory(this);
+		}
+		return modelFactory;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractStructuredGraphViewer#getLayoutAlgorithm()
+	 */
+	protected LayoutAlgorithm getLayoutAlgorithm() {
+		return null;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/SpringGraphViewer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/SpringGraphViewer.java
new file mode 100644
index 0000000..e4c9992
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/SpringGraphViewer.java
@@ -0,0 +1,371 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.editparts.ZoomManager;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModel;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModelEntityFactory;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModelEntityRelationshipFactory;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModelFactory;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphModelNode;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory;
+import org.eclipse.mylar.zest.core.internal.graphviewer.SpringGraphViewerImpl;
+import org.eclipse.mylar.zest.layouts.LayoutAlgorithm;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+
+/**
+ * A very springy viewer.
+ * 
+ * @author Ian Bull
+ * @author Chris Callendar
+ */
+public class SpringGraphViewer extends AbstractStructuredGraphViewer {
+	
+	
+	private SpringGraphViewerImpl viewer = null;
+	private IStylingGraphModelFactory modelFactory = null;
+
+	/**
+	 * Initializes the viewer.  
+	 * @param composite	
+	 * @param style	The styles for this viewer (also passed on to the viewer impl) 
+	 * @see ZestStyles#NODES_HIGHLIGHT_ADJACENT
+	 * @see ZestStyles#PANNING
+	 * @see ZestStyles#MARQUEE_SELECTION
+	 * @see ZestStyles#NO_OVERLAPPING_NODES
+	 * @see ZestStyles#STABILIZE
+	 * @see ZestStyles#ENFORCE_BOUNDS
+	 * @see ZestStyles#DIRECTED_GRAPH
+	 */
+	public SpringGraphViewer(Composite composite, int style) {
+		super(style);
+		this.viewer = new SpringGraphViewerImpl(composite, style);
+		hookControl( this.viewer.getControl() );
+	}
+	
+	/**
+	 * Gets the styles for this structuredViewer
+	 * @return
+	 */
+	public int getStyle() {
+		return this.viewer.getStyle();
+	}
+	
+	/**
+	 * Sets the style on this structuredViewer
+	 * @param style
+	 * @return
+	 */
+	public void setStyle( int style ) {
+		this.viewer.setStyle( style );
+	}
+
+	
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.ContentViewer#setContentProvider(org.eclipse.jface.viewers.IContentProvider)
+	 */
+	public void setContentProvider(IContentProvider contentProvider) {
+		if (contentProvider instanceof IGraphContentProvider) {
+			super.setContentProvider(contentProvider);
+		} else if ( contentProvider instanceof IGraphEntityContentProvider ) {
+			super.setContentProvider( contentProvider );
+		} else if (contentProvider instanceof IGraphEntityRelationshipContentProvider){
+			super.setContentProvider(contentProvider);
+		} else {
+			throw new IllegalArgumentException(
+					"Invalid content provider, only IGraphContentProvider, IGraphEntityContentProvider, or IGraphEntityRelationshipContentProvider are supported.");
+		}
+	}
+
+	protected void inputChanged(Object input, Object oldInput) {
+		viewer.stopLayoutAlgorithm();
+		//boolean highlightAdjacentNodes = ZestStyles.checkStyle(viewer.getStyle(), ZestStyles.NODES_HIGHLIGHT_ADJACENT);
+		if ( getContentProvider() instanceof IGraphContentProvider ) {
+			modelFactory = new GraphModelFactory( this );
+		}
+		else if ( getContentProvider() instanceof IGraphEntityContentProvider ) {
+			modelFactory = new GraphModelEntityFactory( this );
+		}
+		else if (getContentProvider() instanceof IGraphEntityRelationshipContentProvider) {
+//		@tag zest.bug.154580-Content.fix : add new factory here.
+			modelFactory = new GraphModelEntityRelationshipFactory(this);
+		}
+		GraphModel model = createModel();
+		modelFactory.setConnectionStyle(getConnectionStyle());
+		modelFactory.setNodeStyle(getNodeStyle());
+		model = modelFactory.createGraphModel();
+
+		// set the model contents (initializes the layout algorithm)
+		model.setNodeStyle(getNodeStyle());
+		model.setConnectionStyle(getConnectionStyle());
+		viewer.setContents(model, modelFactory);
+		
+	}
+	
+	/**
+	 * Sets a single node as selected and moves it to the center.
+	 * While selected the node will be pinned! 
+	 * @param itemToCenter
+	 */
+	public void setCenterSelection( Object itemToCenter, int x, int y ) {
+		if( getModel().getInternalNode( itemToCenter ) == null ) {
+			// noop
+		} else {
+			viewer.setCenterSelection( getModel().getInternalNode(itemToCenter), x, y );
+		}
+	}
+
+	
+	/**
+	 * Gets the (first) selected node object.  If no nodes are selected
+	 * then null is returned.
+	 * @return Object the external node data object.
+	 */
+	public Object getSelectedNode() {
+		Object node = null;
+		if (getSelection() instanceof StructuredSelection) {
+			StructuredSelection selection = (StructuredSelection) getSelection();
+			node = selection.getFirstElement();
+		}
+		return node;
+	}
+	
+	// @tag TODO : Reduce the visibility of getViewer
+	public SpringGraphViewerImpl getViewer() {
+		return viewer;
+	}
+	
+	/**
+	 * Adds a new node to the graph
+	 * @param o The new node to add
+	 */
+	public void addNode( Object o ) {
+		viewer.addNode( o );
+	}
+	
+	/**
+	 * Adds a set of new nodes to the graph
+	 * @param o An arry of nodes to add
+	 */
+	public void addNode( Object[] o ) {
+		for ( int i = 0; i < o.length; i++ ) {
+			addNode( o[i] );
+		}
+	}
+	
+	/**
+	 * Adds a new relalationship to the graph
+	 * @param connection The connection (or null)
+	 * @param src The src node
+	 * @param dest The dest node
+	 * 
+	 * If Connection is not null then src and dest can be quiried from the content
+	 * provider
+	 */
+	public void addRelationship( Object connection, Object src, Object dest ) {
+		viewer.addRelationship( connection, src, dest );
+	}
+	
+	public void zoomIn() {
+		viewer.zoomIn();
+	}
+	
+	public void zoomOut() {
+		viewer.zoomOut();
+	}
+	
+	/**
+	 * Updates the relationship's weight.
+	 * @param relationship the data object for the relationship to update
+	 * @param weight the new weight
+	 */
+	public void updateRelationshipWeight(Object relationship, double weight) {
+		viewer.updateRelationshipWeight(relationship, weight);
+	}	
+
+	// StructuredViewer overrides
+	
+	public Control getControl() {
+		return viewer.getControl();
+	}
+	
+//	/**
+//	 * Gets the selected model elements as a List.
+//	 * @return List
+//	 */
+//	protected List getSelectionFromWidget() {
+//		Widget[] items = viewer.getSelectedModelElements();
+//		ArrayList list = new ArrayList(items.length);
+//		for (int i = 0; i < items.length; i++) {
+//			Widget item = items[i];
+//			Object e = item.getData();
+//			if (e != null)
+//				list.add(e);
+//		}
+//		return list;
+//	}
+//
+//	protected void setSelectionToWidget(List l, boolean reveal) {
+//		ArrayList widgetList = new ArrayList( l.size() );
+//		for ( int i = 0; i < l.size(); i++ ) {
+//			widgetList.add(i, getModel().getInternalNode( l.get( i )));
+//		}
+//		//DebugPrint.println("Highlighting: " + widgetList.size() + " starting wtih: " + l.size() );
+//		viewer.setSelection(new StructuredSelection( widgetList ));
+//	}
+//	
+//	/**
+//	 * Returns the input item (in this case the GraphModel object) if the given element
+//	 * equals the root element, otherwise null is returned.
+//	 * @see org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object)
+//	 */
+//	protected Widget doFindInputItem(Object element) {
+//		if (equals(element, getRoot())) {
+//			return getModel();
+//		}
+//		return null;
+//	}
+//
+//	/**
+//	 * Returns the node (widget) for the given element.
+//	 * @see org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object)
+//	 */
+//	protected Widget doFindItem(Object element) {
+//		if (getModel() != null) {
+//			Object o = getModel().getInternalNode( element );
+//			if (o instanceof Widget)
+//				return (Widget)o;
+//		}
+//		return null;
+//	}
+//
+//	/* (non-Javadoc)
+//	 * @see org.eclipse.jface.viewers.StructuredViewer#doUpdateItem(org.eclipse.swt.widgets.Widget, java.lang.Object, boolean)
+//	 */
+//	protected void doUpdateItem(Widget widget, Object element, boolean fullMap) {
+//		if (widget instanceof GraphItem) {
+//			final GraphItem item = (GraphItem)widget;
+//			if (fullMap) {
+//				associate(element, item);
+//			} else {
+//				item.setData(element);
+//				mapElement(element, item);
+//			}	
+//		}
+//	}
+//
+//	/**
+//	 * Refreshes the given element.  If this element is the root element
+//	 * then all the nodes are refreshed, otherwise just the one element is refreshed.
+//	 * @param element the element to refresh. 
+//	 */
+//	protected void internalRefresh(Object element) {
+//		//DebugPrint.println("internalRefresh");
+//		if ((element == null) || equals(element, getRoot())) {
+//			internalRefreshAll();
+//		} else {
+//			Widget widget = findItem(element);
+//			if (widget != null) {
+//				updateItem(widget, element);
+//			}
+//		}
+//	}
+//	
+//	/**
+//	 * Refreshes all the nodes in the model.
+//	 */
+//	protected void internalRefreshAll() {
+//		if (model != null) {
+//			List nodes = model.getNodes();
+//			for (Iterator iter = nodes.iterator(); iter.hasNext(); ) {
+//				IGraphModelNode node = (IGraphModelNode)iter.next();
+//				Object o = node.getExternalNode();
+//				if (node instanceof Widget) {
+//					updateItem((Widget)node, o);
+//				}
+//			}
+//		}
+//	}
+//
+//	/**
+//	 * Centers the given element on the canvas.
+//	 */
+	public void reveal(Object element) {
+		if ((getModel() != null) && (element != null)) {
+			IGraphModelNode nodeToCenter = getModel().getInternalNode(element);
+			if (nodeToCenter != null) {
+				viewer.centerNodeInCanvas(nodeToCenter);
+			}
+		}
+	}
+
+	/** 
+	 * SpringGraphViewer is designed for spring graph layouts only. This method is ignored.
+	 */
+	public void setLayoutAlgorithm(LayoutAlgorithm algorithm, boolean run) {
+				
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractZoomableViewer#getZoomManager()
+	 */
+	protected ZoomManager getZoomManager() {
+		//@tag bug.156286-Zooming.todo : add zooming capabilities on the SpringGraphViewer
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractStructuredGraphViewer#applyLayout()
+	 */
+	public void applyLayout() {
+		//do nothing spring viewers always are layed out?
+		//@tag zest.check : how does the spring graph viewer layout actually work?
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractStructuredGraphViewer#getLayoutAlgorithm()
+	 */
+	protected LayoutAlgorithm getLayoutAlgorithm() {
+		return viewer.getLayoutAlgorithm();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractStructuredGraphViewer#getEditPartViewer()
+	 */
+	protected EditPartViewer getEditPartViewer() {
+		return viewer;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractStructuredGraphViewer#getFactory()
+	 */
+	protected IStylingGraphModelFactory getFactory() {
+		if (modelFactory == null) {
+			if (getContentProvider() instanceof IGraphContentProvider) {
+				modelFactory = new GraphModelFactory(this);
+			} else if (getContentProvider() instanceof IGraphEntityContentProvider) {
+				modelFactory = new GraphModelEntityFactory(this);
+			} else if (getContentProvider() instanceof IGraphEntityRelationshipContentProvider) {
+				modelFactory = new GraphModelEntityRelationshipFactory(this);
+			}
+		}
+		return modelFactory;
+	}
+
+}
+	
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/StaticGraphViewer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/StaticGraphViewer.java
new file mode 100644
index 0000000..afe33c5
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/StaticGraphViewer.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import java.util.List;
+
+import org.eclipse.gef.EditPartViewer;
+import org.eclipse.gef.editparts.ZoomManager;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.mylar.zest.core.ZestStyles;
+import org.eclipse.mylar.zest.core.internal.gefx.StaticGraphRootEditPart;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModelEntityFactory;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModelEntityRelationshipFactory;
+import org.eclipse.mylar.zest.core.internal.graphmodel.GraphModelFactory;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IGraphItem;
+import org.eclipse.mylar.zest.core.internal.graphmodel.IStylingGraphModelFactory;
+import org.eclipse.mylar.zest.core.internal.graphviewer.StaticGraphViewerImpl;
+import org.eclipse.mylar.zest.layouts.LayoutAlgorithm;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * This view is used to represent a static graph. Static graphs can be layed
+ * out, but do not continually update their layout locations.
+ * 
+ * @author Ian Bull
+ * @author Chris Callendar
+ */
+public class StaticGraphViewer extends AbstractStructuredGraphViewer {
+
+	StaticGraphViewerImpl viewer = null;
+	private IStylingGraphModelFactory modelFactory = null;
+
+
+	/**
+	 * Initializes the viewer.
+	 * 
+	 * @param composite
+	 * @param style
+	 *            the style for the viewer and for the layout algorithm
+	 * @see ZestStyles#LAYOUT_GRID
+	 * @see ZestStyles#LAYOUT_TREE
+	 * @see ZestStyles#LAYOUT_RADIAL
+	 * @see ZestStyles#LAYOUT_SPRING
+	 * @see ZestStyles#NO_OVERLAPPING_NODES
+	 * @see ZestStyles#NODES_HIGHLIGHT_ADJACENT
+	 * @see SWT#V_SCROLL
+	 * @see SWT#H_SCROLL
+	 */
+	public StaticGraphViewer(Composite composite, int style) {
+		super(style);
+		this.viewer = new StaticGraphViewerImpl(composite, style);
+		hookControl(this.viewer.getControl());
+	}
+
+	/**
+	 * Gets the styles for this structuredViewer
+	 * 
+	 * @return
+	 */
+	public int getStyle() {
+		return this.viewer.getStyle();
+	}
+
+	/**
+	 * Sets the horizontal scale
+	 * 
+	 * @param scale
+	 */
+	public void setHorizontalScale(double scale) {
+		this.viewer.setScale(scale, this.viewer.getHeightScale());
+	}
+
+	/**
+	 * Sets the horizontal scale
+	 * 
+	 * @param scale
+	 */
+	public void setVerticalScale(double scale) {
+		this.viewer.setScale(this.viewer.getWidthScale(), scale);
+	}
+
+	/**
+	 * Sets the scale in both the X and Y
+	 * 
+	 * @param scale
+	 */
+	public void setScale(double scale) {
+		this.viewer.setScale(scale, scale);
+	}
+
+	/**
+	 * Sets the style on this structuredViewer
+	 * 
+	 * @param style
+	 * @return
+	 */
+	public void setStyle(int style) {
+		this.viewer.setStyle(style);
+	}
+
+	/**
+	 * Sets the layout algorithm to use for this viewer.
+	 * 
+	 * @param algorithm
+	 *            the algorithm to layout the nodes
+	 * @param runLayout
+	 *            if the layout should be run
+	 */
+	public void setLayoutAlgorithm(LayoutAlgorithm algorithm, boolean runLayout) {
+		viewer.setLayoutAlgorithm(algorithm, runLayout);
+	}
+
+	public void setContentProvider(IContentProvider contentProvider) {
+		if (contentProvider instanceof IGraphContentProvider) {
+			super.setContentProvider(contentProvider);
+		} else if (contentProvider instanceof IGraphEntityContentProvider) {
+			super.setContentProvider(contentProvider);
+		} else if (contentProvider instanceof IGraphEntityRelationshipContentProvider){
+			super.setContentProvider(contentProvider);
+		} else {
+			throw new IllegalArgumentException(
+					"Invalid content provider, only IGraphContentProvider, IGraphEntityContentProvider, or IGraphEntityRelationshipContentProvider are supported.");
+		}
+	}
+	
+	
+	/**
+	 * Finds the graph widget item for a given user model item.  
+	 * 
+	 * Note:  This method returns an internal interface (GraphItem).  You should be able to cast this 
+	 * to either a IGraphModelNode or IGraphModelConnection (which are also internal). These are internal
+	 * because this API is not stable.  If use this method (to access internal nodes and edges), your code may not
+	 * compile between versions.  
+	 * 
+	 * @param The user model node.
+	 * @return  An IGraphItem.  This should be either a IGraphModelNode or IGraphModelConnection
+	 */
+	public IGraphItem findGraphItem(Object element) {
+		Widget[] result = findItems(element);
+		return (result.length == 0 && result[0] instanceof IGraphItem)? null : (IGraphItem)result[0];
+	}
+	
+
+	/**
+	 * Applys the current layout to the viewer
+	 */
+	public void applyLayout() {
+		if (viewer.hasLayoutRun()) {
+			viewer.applyLayout();
+		}
+	}
+
+
+
+	protected void setSelectionToWidget(List l, boolean reveal) {
+		viewer.setSelection(l);
+	}
+
+	public Control getControl() {
+		return viewer.getControl();
+	}
+	
+	/**
+	 * Gets the internal static graph.  Becareful when using this because the static graph viewer impl may change.
+	 * @return
+	 */
+	public StaticGraphViewerImpl getStaticGraph() {
+		return this.viewer;
+	}
+
+	
+	public void addSelectionChangedListener(ISelectionChangedListener listener) {
+		viewer.addSelectionChangedListener(listener);
+	}
+	public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+		viewer.removeSelectionChangedListener(listener);
+	}
+	
+	//@tag zest.bug.156286-Zooming.fix.experimental : expose the zoom manager for new actions.
+	protected ZoomManager getZoomManager() {
+		return ((StaticGraphRootEditPart)viewer.getRootEditPart()).getZoomManager();
+	}
+
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractStructuredGraphViewer#getEditPartViewer()
+	 */
+	protected EditPartViewer getEditPartViewer() {
+		return viewer;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractStructuredGraphViewer#getFactory()
+	 */
+	protected IStylingGraphModelFactory getFactory() {
+		if (modelFactory == null) {
+			if (getContentProvider() instanceof IGraphContentProvider) {
+				modelFactory = new GraphModelFactory(this);
+			} else if (getContentProvider() instanceof IGraphEntityContentProvider) {
+				modelFactory = new GraphModelEntityFactory(this);
+			} else if (getContentProvider() instanceof IGraphEntityRelationshipContentProvider) {
+				modelFactory = new GraphModelEntityRelationshipFactory(this);
+			}
+		}
+		return modelFactory;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.AbstractStructuredGraphViewer#getLayoutAlgorithm()
+	 */
+	protected LayoutAlgorithm getLayoutAlgorithm() {
+		return viewer.getLayoutAlgorithm();
+	}
+	
+	
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/TreeGraphViewer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/TreeGraphViewer.java
new file mode 100644
index 0000000..21c105a
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/TreeGraphViewer.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.mylar.zest.core.internal.treegraphviewer.TreeGraphViewerImpl;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * 
+ * @author Ian Bull
+ */
+public class TreeGraphViewer extends StructuredViewer {
+
+	TreeGraphViewerImpl viewer = null;
+
+	public TreeGraphViewer(Composite composite, int style) {
+		this.viewer = new TreeGraphViewerImpl(composite, style);
+	}
+	
+	
+	protected void inputChanged(Object input, Object oldInput) {
+		ITreeContentProvider contentProvider = (ITreeContentProvider) getContentProvider();
+		ILabelProvider labelProvider = (ILabelProvider)getLabelProvider();
+		this.viewer.setContents(input, contentProvider, labelProvider);
+	}
+	
+	protected Widget doFindInputItem(Object element) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	protected Widget doFindItem(Object element) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	protected void doUpdateItem(Widget item, Object element, boolean fullMap) {
+		// TODO Auto-generated method stub
+
+	}
+
+	protected List getSelectionFromWidget() {
+		return Collections.EMPTY_LIST;
+	}
+
+	protected void internalRefresh(Object element) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void reveal(Object element) {
+		// TODO Auto-generated method stub
+
+	}
+
+	protected void setSelectionToWidget(List l, boolean reveal) {
+		// TODO Auto-generated method stub
+
+	}
+
+	public Control getControl() {
+		// TODO Auto-generated method stub
+		return viewer;
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/TreeRootViewer.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/TreeRootViewer.java
new file mode 100644
index 0000000..4b23818
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/TreeRootViewer.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.swt.widgets.Widget;
+
+
+/**
+ * Extends the JFace {@linke TreeViewer} to automatically create a 
+ * Root item from the given data {@link Item}.  All {@link TreeItem} objects
+ * are then created under this item.
+ * 
+ * @author Chris Callendar
+ */
+public class TreeRootViewer extends TreeViewer {
+
+	private Item dataItem = null;
+	private TreeItem rootTreeItem = null;
+	
+	public TreeRootViewer(Composite parent, int style) {
+		super(parent, style);
+	}
+	
+	public void setRootDataItem(Item rootDataItem) {
+		if (rootDataItem != null) {
+			this.dataItem = rootDataItem;
+		}
+	}
+	
+	/**
+	 * Gets the root data Item.  
+	 * @see #setRootDataItem(Item)
+	 * @return Item or null if it hasn't been set
+	 */
+	public Item getRootDataItem() {
+		return dataItem;
+	}
+	
+	/**
+	 * Creates a new item.  If the parent is the Tree and 
+	 * {@link #setRootDataItem(Item)} has been called then 
+	 * a root TreeItem will be created which all other TreeItems will go under.
+	 * @see org.eclipse.jface.viewers.TreeViewer#newItem(org.eclipse.swt.widgets.Widget, int, int)
+	 */
+	protected Item newItem(Widget parent, int flags, int ix) {
+		if (parent instanceof Tree) {
+			Item rootItem = getRootDataItem();
+			if (rootItem != null) {
+				parent = createRootItem((Tree)parent, rootItem);
+			}
+		}
+		return super.newItem(parent, flags, ix);
+	}
+	
+	/**
+	 * Creates the root item with the Tree as its parent.
+	 * @param tree
+	 * @return the root TreeItem for convenience
+	 */
+	private TreeItem createRootItem(Tree tree, Item rootItem) {
+		if (rootItem == null)
+			throw new IllegalArgumentException("Root item cannot be null");
+		
+		if ((rootTreeItem == null) || rootTreeItem.isDisposed()) {
+			rootTreeItem = new TreeItem(tree, SWT.NULL, 0);
+			rootTreeItem.setText(rootItem.getText());
+			rootTreeItem.setImage(rootItem.getImage());
+			rootTreeItem.setData(rootItem);	// can't be null
+			mapElement(dataItem, rootTreeItem);			
+		}
+		return rootTreeItem;
+	}
+
+	/**
+	 * Tries to get the TreeItem associated with the given object.
+	 * @param data
+	 * @return TreeItem or null if not found.
+	 */
+	public TreeItem getTreeItem(Object data) {
+		TreeItem item = (TreeItem)findItem(data);
+		return item;
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/ZoomContributionViewItem.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/ZoomContributionViewItem.java
new file mode 100644
index 0000000..4a77933
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/ZoomContributionViewItem.java
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.gef.editparts.ZoomListener;
+import org.eclipse.gef.editparts.ZoomManager;
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.CoolBar;
+import org.eclipse.swt.widgets.CoolItem;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.IPartService;
+import org.eclipse.ui.IWorkbenchPart;
+
+/**
+ * A contribution item that adds a combo to a toolbar or coolbar, or a
+ * list of zooms to a menu. Can only be used for one toolbar, coolbar, or
+ * menu.
+ * 
+ * In order to use this item, let your workbench part implement IZoomableWorkbenchPart.
+ * If the workbench part then supplies a viewer that is zoomable, the combo
+ * or menu created by this item will be enabled.
+ * @author Del Myers
+ *
+ */
+//@tag zest.bug.156286-Zooming.fix : create a contribution item that can set zooming on Zest views.
+public class ZoomContributionViewItem extends ContributionItem implements ZoomListener {
+	/**
+	 * Zooms to fit the width.
+	 */
+	public static final String FIT_WIDTH = ZoomManager.FIT_WIDTH;
+	/**
+	 * Zooms to fit the height.
+	 */
+	public static final String FIT_HEIGHT = ZoomManager.FIT_HEIGHT;
+	/**
+	 * Zooms to fit entirely within the viewport.
+	 */
+	public static final String FIT_ALL = ZoomManager.FIT_ALL;
+	
+	
+	private String[] zoomLevels;
+	private ZoomManager zoomManager;
+	private Combo combo;
+	private Menu fMenu;
+	private ZoomablePartListener partListener;
+	//@tag zest.bug.159667-ZoomDispose : cache the part service so that we can properly dispose this item.
+	private IPartService partSevice;
+	
+	private class ZoomablePartListener implements IPartListener {
+		public void partActivated(IWorkbenchPart part) {
+			if (part instanceof IZoomableWorkbenchPart) {
+				if (zoomManager != null) {
+					zoomManager.removeZoomListener(ZoomContributionViewItem.this);
+				}
+				zoomManager = ((IZoomableWorkbenchPart)part).getZoomableViewer().getZoomManager();
+				if (zoomManager != null) {
+					zoomManager.addZoomListener(ZoomContributionViewItem.this);
+				}
+				refresh(true);
+			}
+		}
+		public void partDeactivated(IWorkbenchPart part) {
+			if (part instanceof IZoomableWorkbenchPart) {
+				if (zoomManager != null) {
+					zoomManager.removeZoomListener(ZoomContributionViewItem.this);
+				}
+				zoomManager = ((IZoomableWorkbenchPart)part).getZoomableViewer().getZoomManager();
+				refresh(true);
+			}
+		}
+	
+		public void partBroughtToTop(IWorkbenchPart part) {}
+		public void partClosed(IWorkbenchPart part) {}
+		
+		public void partOpened(IWorkbenchPart part) {}
+		
+	}
+	
+	
+	public ZoomContributionViewItem(IPartService partService) {
+		this(partService, new String[] {"20%", "50%", "100%", "120%", "150%", "175%", "200%"});
+	}
+	
+	/**
+	 * Creates a new contribution item that will work on the given part
+	 * service.initialZooms will be used to populate the combo or the menu.
+	 * Valid values for initialZooms are percentage numbers (e.g., "100%"),
+	 * or FIT_WIDTH, FIT_HEIGHT, FIT_ALL.
+	 * 
+	 * @param partService service used to see whether the view is zoomable.
+	 * @param initialZooms the initial zoom values.
+	 */
+	public ZoomContributionViewItem(IPartService partService, String[] initialZooms) {
+		this.zoomLevels = initialZooms;
+		this.partListener = new ZoomablePartListener();
+		this.partSevice = partService;
+		partService.addPartListener(partListener);
+		//@tag zest.bug.159647 : if we are in the ui thread initialize the part listener.
+		if (Display.getCurrent() != null) {
+			IWorkbenchPart part = partService.getActivePart();
+			partListener.partActivated(part);
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.action.ContributionItem#fill(org.eclipse.swt.widgets.Menu, int)
+	 */
+	public void fill(Menu menu, int index) {
+		this.fMenu = menu;
+		for (int i = 0; i < zoomLevels.length; i++) {
+			final MenuItem item = new MenuItem(fMenu, SWT.RADIO);
+			if( zoomManager.getZoomAsText().equals(zoomLevels[i])) {
+				item.setSelection(true);
+			}
+			item.setText(zoomLevels[i]);
+			item.addSelectionListener(new SelectionAdapter() {
+				public void widgetSelected(SelectionEvent e) {
+					doZoom(item.getText());
+				}
+			});
+		}
+	}
+	
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.action.ContributionItem#fill(org.eclipse.swt.widgets.CoolBar, int)
+	 */
+	public void fill(CoolBar parent, int index) {
+		CoolItem item = new CoolItem(parent, SWT.DROP_DOWN);
+		Combo combo = createCombo(parent);
+		item.setControl(combo);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.action.ContributionItem#fill(org.eclipse.swt.widgets.ToolBar, int)
+	 */
+	public void fill(ToolBar parent, int index) {
+		ToolItem item = new ToolItem(parent, SWT.DROP_DOWN);
+		Combo combo = createCombo(parent);
+		item.setControl(combo);
+	}
+	
+	private Combo createCombo(Composite parent) {
+		this.combo = new Combo(parent, SWT.DROP_DOWN);
+		this.combo.setItems(zoomLevels);
+		this.combo.addSelectionListener(new SelectionAdapter() {
+			/* (non-Javadoc)
+			 * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+			 */
+			public void widgetSelected(SelectionEvent e) {
+				int selection = combo.getSelectionIndex();
+				if (selection >0) {
+					doZoom(combo.getItem(selection));
+				} else {
+					doZoom(combo.getItem(0));
+				}
+			}
+		});
+		return this.combo;
+	}
+	
+	private void doZoom(String zoom) {
+		if (zoomManager != null) {
+			zoomManager.setZoomAsText(zoom);
+		}
+	}
+	
+	private void refresh(boolean rebuild) {
+		//
+		if (combo != null && !combo.isDisposed()) {
+			refreshCombo(rebuild);
+		} else if (fMenu != null && fMenu.isDisposed()) {
+			refreshMenu(rebuild);
+		}
+	}
+	
+	/**
+	 * @param rebuild
+	 */
+	private void refreshMenu(boolean rebuild) {
+		fMenu.setEnabled(false);
+		if (zoomManager == null) {
+			return;
+		}
+		if (rebuild) {
+			zoomLevels = zoomManager.getZoomLevelsAsText();
+			MenuItem[] oldItems = fMenu.getItems();
+			for (int i = 0; i < oldItems.length; i++) {
+				oldItems[i].dispose();
+			}
+			for (int i = 0; i < zoomLevels.length;i++) {
+				MenuItem item = new MenuItem(fMenu, SWT.RADIO);
+				item.setText(zoomLevels[i]);
+				item.addSelectionListener(new SelectionAdapter(){
+					public void widgetSelected(SelectionEvent e) {
+						MenuItem source = (MenuItem)e.getSource();
+						doZoom(source.getText());
+					}
+				});
+			}
+		}
+		MenuItem[] items = fMenu.getItems();
+		String zoom = zoomManager.getZoomAsText();
+		for (int i = 0; i < items.length; i++) {
+			items[i].setSelection(false);
+			if (zoom.equalsIgnoreCase(items[i].getText())) {
+				items[i].setSelection(true);
+			}
+		}
+		fMenu.setEnabled(true);
+	}
+
+	/**
+	 * @param rebuild
+	 */
+	private void refreshCombo(boolean rebuild) {
+		combo.setEnabled(false);
+		if (zoomManager == null) {
+			return;
+		}
+		if (rebuild) {
+			combo.setItems(zoomManager.getZoomLevelsAsText());
+		}	
+		String zoom = zoomManager.getZoomAsText();
+		int index = combo.indexOf(zoom);
+		if (index > 0) {
+			combo.select(index);
+		}
+		combo.setEnabled(true);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.gef.editparts.ZoomListener#zoomChanged(double)
+	 */
+	public void zoomChanged(double z) {
+		refresh(false);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.action.ContributionItem#dispose()
+	 */
+	
+	public void dispose() {
+		if (combo != null) {
+			combo = null;
+		}
+		if (fMenu != null) {
+			fMenu = null;
+		}
+//		@tag zest.bug.159667-ZoomDispose : make sure that we no longer listen to the part service.
+		partSevice.removePartListener(partListener);
+		super.dispose();
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/ZoomInViewerAction.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/ZoomInViewerAction.java
new file mode 100644
index 0000000..c65b182
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/ZoomInViewerAction.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.gef.ui.actions.ZoomInAction;
+
+/**
+ * An action that can be contributed for zoomable viewers.
+ * @author Del Myers
+ *
+ */
+//@tag zest.bug.156286-Zooming.fix
+public class ZoomInViewerAction extends ZoomInAction {
+	public static final String ID = "zest.actions.zoomin";
+	public ZoomInViewerAction(AbstractZoomableViewer viewer) {
+		super(viewer.getZoomManager());
+	}
+	public String getId() {
+		return ID;
+	}
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/ZoomOutViewerAction.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/ZoomOutViewerAction.java
new file mode 100644
index 0000000..48f68a4
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/viewers/ZoomOutViewerAction.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.viewers;
+
+import org.eclipse.gef.ui.actions.ZoomOutAction;
+
+/**
+ * An action for zooming out on Zest Viewers.
+ * @author Del Myers
+ *
+ */
+public class ZoomOutViewerAction extends ZoomOutAction {
+	public static final String ID = "zest.action.zoomout";
+	/**
+	 * Creates a new action for the given viewer.
+	 * @param viewer the viewer to zoom out on.
+	 */
+	public ZoomOutViewerAction(AbstractZoomableViewer viewer) {
+		super(viewer.getZoomManager());
+	}
+	public String getId() {
+		return ID;
+	}
+}
\ No newline at end of file
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/widgets/BreadCrumbBar.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/widgets/BreadCrumbBar.java
new file mode 100644
index 0000000..b6eaa52
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/widgets/BreadCrumbBar.java
@@ -0,0 +1,437 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.widgets;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.eclipse.draw2d.FigureUtilities;
+import org.eclipse.draw2d.geometry.Dimension;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * The BreadCrumbBar class holds a Group control which has a Link control inside it.
+ * Adding breadcrumb items will put hyperlinks into the Link object separated by the separator
+ * character.
+ * 
+ * @author Chris Callendar
+ */
+public class BreadCrumbBar extends Composite implements SelectionListener {
+
+	public static final char SEPARATOR_CHAR = '>';
+
+	private Group group;
+	private ToolBar toolbar;
+	private ToolItem backToolItem;
+	private ToolItem forwardToolItem;
+	private ToolItem upToolItem;
+	private Link link;
+	private GridData groupGridData;
+	private GridData toolbarGridData;
+	private GridData linkGridData;
+	private GridData breadCrumbGridData;
+	private ArrayList listeners;
+	private ArrayList breadCrumbs;
+	private char separatorChar;
+	
+	private ISharedImages sharedImages;
+	
+	
+	/**
+	 * Initializes the BreadCrumbBar.
+	 * @param parent	The parent object.
+	 * @param style		The style for this BreadCrumbBar.
+	 */
+	public BreadCrumbBar(Composite parent, int style) {
+		super(parent, style);
+		this.listeners = new ArrayList();
+		this.breadCrumbs = new ArrayList();
+		this.separatorChar = SEPARATOR_CHAR;
+		this.sharedImages = PlatformUI.getWorkbench().getSharedImages();
+
+		GridLayout layout = new GridLayout(1, true);
+		layout.marginHeight = 0;
+		layout.marginWidth = 0;
+		this.setLayout(layout);
+		this.breadCrumbGridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL, GridData.VERTICAL_ALIGN_BEGINNING, true, false);
+		this.setLayoutData(breadCrumbGridData);
+
+		initializeGroup();
+		initializeToolbar();
+		initializeLink();
+
+		group.pack();
+	}
+
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.widgets.Widget#dispose()
+	 */
+	public void dispose() {
+		super.dispose();
+		listeners.clear();
+	}
+
+	
+	private void initializeGroup() {
+		this.group = new Group(this, SWT.SHADOW_ETCHED_OUT);
+		//group.setText("Breadcrumb");
+		GridLayout groupLayout = new GridLayout(2, false);
+		groupLayout.marginHeight = 0;
+		group.setLayout(groupLayout);
+		groupGridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL, GridData.VERTICAL_ALIGN_FILL, true, true);
+		groupGridData.widthHint = 600;
+		groupGridData.heightHint = 24;
+		groupGridData.minimumHeight = 18;
+		group.setLayoutData(groupGridData);
+	}
+	
+	/**
+	 * Initializes the toolbar and adds the back/forward/up buttons and a separator.
+	 * The three buttons are all disabled to start with.  As bread crumbs are added and clicked 
+	 * the buttons will be enabled.
+	 */
+	private void initializeToolbar() {
+		this.toolbar = new ToolBar(group, SWT.FLAT | SWT.HORIZONTAL | SWT.RIGHT);
+		
+		// Back button
+		this.backToolItem = new ToolItem(toolbar, SWT.PUSH);
+		//backToolItem.setText("Back");
+		backToolItem.setToolTipText("Back");
+		backToolItem.setImage(sharedImages.getImage(ISharedImages.IMG_TOOL_BACK));
+		backToolItem.setDisabledImage(sharedImages.getImage(ISharedImages.IMG_TOOL_BACK_DISABLED));
+		backToolItem.addSelectionListener(this);
+		backToolItem.setEnabled(false);
+		// Forward button
+		this.forwardToolItem = new ToolItem(toolbar, SWT.PUSH);
+		//forwardToolItem.setText("Forward");
+		forwardToolItem.setToolTipText("Forward");
+		forwardToolItem.setImage(sharedImages.getImage(ISharedImages.IMG_TOOL_FORWARD));
+		forwardToolItem.setDisabledImage(sharedImages.getImage(ISharedImages.IMG_TOOL_FORWARD_DISABLED));
+		forwardToolItem.addSelectionListener(this);
+		forwardToolItem.setEnabled(false);
+		// Up button
+		this.upToolItem = new ToolItem(toolbar, SWT.PUSH);
+		//upToolItem.setText(UP);
+		upToolItem.setToolTipText("Up one level");
+		upToolItem.setImage(sharedImages.getImage(ISharedImages.IMG_TOOL_UP));
+		upToolItem.setDisabledImage(sharedImages.getImage(ISharedImages.IMG_TOOL_UP_DISABLED));
+		upToolItem.addSelectionListener(this);
+		upToolItem.setEnabled(false);
+		
+		new ToolItem(toolbar, SWT.SEPARATOR);
+		
+		this.toolbarGridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING, GridData.VERTICAL_ALIGN_BEGINNING, false, false);
+		toolbar.setLayoutData(toolbarGridData);		
+	}
+	
+	private void initializeLink() {
+		this.link = new Link(group, SWT.NONE);
+		link.addSelectionListener(this);
+		this.linkGridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL, GridData.VERTICAL_ALIGN_BEGINNING, true, false);
+		link.setLayoutData(linkGridData);
+	}
+	
+	// SelectionListener methods
+	public void widgetDefaultSelected(SelectionEvent e) {
+		widgetSelected(e);
+	}
+		
+	public void widgetSelected(SelectionEvent e) {
+		Object src = e.getSource();
+		if (src instanceof Link) {
+			linkSelected((Link)src, e.text);
+		} else if (src instanceof ToolItem) {
+			toolItemSelected((ToolItem)src);
+		}
+	}
+	
+	private void linkSelected(Link lnk, String text) {
+		ArrayList list = (ArrayList)lnk.getData();
+		int index = -1;
+		try {
+			index = Integer.parseInt(text);
+		} catch (Exception ex) {
+			ex.printStackTrace();
+		}
+		if ((index >= 0) && (index < list.size())) {
+			BreadCrumbItem item = (BreadCrumbItem)list.get(index);
+			for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
+				IBreadCrumbListener bcl = (IBreadCrumbListener)iter.next();
+				bcl.breadCrumbSelected(item);
+			}
+		}
+	}
+	
+	private void toolItemSelected(ToolItem toolItem) {
+		//Object data = toolItem.getData();
+		if (toolItem == upToolItem) {
+			up();
+		} else if (toolItem == backToolItem) {
+			back();
+		} else if (toolItem == forwardToolItem) {
+			forward();
+		}
+	}
+	
+	private void back() {
+		for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
+			IBreadCrumbListener bcl = (IBreadCrumbListener)iter.next();
+			bcl.handleBackButtonSelected();
+		}
+	}
+	
+	private void forward() {
+		for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
+			IBreadCrumbListener bcl = (IBreadCrumbListener)iter.next();
+			bcl.handleForwardButtonSelected();
+		}
+	}
+	
+	private void up() {
+		for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
+			IBreadCrumbListener bcl = (IBreadCrumbListener)iter.next();
+			bcl.handleUpButtonSelected();
+		}
+	}
+	
+	/**
+	 * Adds a listener to the list.  When a breadcrumb is selected 
+	 * any listener in the list will be notified
+	 * @param listener
+	 */
+	public void addBreadCrumbListener(IBreadCrumbListener listener) {
+		if (!this.listeners.contains(listener)) this.listeners.add(listener);
+	}
+	
+	/**
+	 * Removes the given listener from the list.
+	 * @param listener the listener to remove.
+	 */
+	public void removeBreadCrumbListener(IBreadCrumbListener listener) {
+		this.listeners.remove(listener);
+	}
+
+	/**
+	 * Sets the back button to be enabled or disabled.
+	 * @param enabled
+	 */
+	public void setBackEnabled(boolean enabled) {
+		backToolItem.setEnabled(enabled);
+	}
+
+	/**
+	 * Sets the forward button to be enabled or disabled.
+	 * @param enabled
+	 */
+	public void setForwardEnabled(boolean enabled) {
+		forwardToolItem.setEnabled(enabled);
+	}
+
+	/**
+	 * Sets the up button to be enabled or disabled.
+	 * @param enabled
+	 */
+	public void setUpEnabled(boolean enabled) {
+		upToolItem.setEnabled(enabled);
+	}
+
+	/**
+	 * Gets the last breadcrumb in the list, or null if the list is empty.
+	 * @return BreadCrumbItem the last in the list
+	 */
+	protected BreadCrumbItem getLastBreadCrumb() {
+		BreadCrumbItem item = null;
+		if (breadCrumbs.size() > 0) {
+			item = (BreadCrumbItem)breadCrumbs.get(breadCrumbs.size() - 1);
+		}
+		return item;
+	}
+
+	/**
+	 * Clears all the breadCrumbs.  The old breadcrumbs
+	 * are saved in case the back button is clicked.
+	 */
+	public void clearItems() {
+		if (breadCrumbs.size() > 0) {
+			breadCrumbs.clear();
+		}
+	}
+
+	/**
+	 * Adds an item at the given index and updates the link text with the given item.
+	 * @param item	The item to add.
+	 * @param index The position to add the new item.
+	 */
+	public void createItem(BreadCrumbItem item, int index) {
+		breadCrumbs.add(index, item);
+		updateLinkText();
+	}
+	
+	
+	private static final String AOPEN = "<a href=\"X\">";
+	private static final String ACLOSE = "</a>";
+	private static final String SPC = " ";
+	
+	private void updateLinkText() {
+		StringBuffer buffer = new StringBuffer();
+		StringBuffer notags = new StringBuffer(SPC);
+		final String SEP = "  " + separatorChar + "  ";
+		for (int i = 0; i < breadCrumbs.size(); i++) {
+			String href = "" + i;
+			BreadCrumbItem item = (BreadCrumbItem)breadCrumbs.get(i);
+			if (buffer.length() > 0) {
+				buffer.append(SEP);
+				notags.append(SEP);
+			}
+			if (i < (breadCrumbs.size()-1)) {
+				String anchor = AOPEN.replaceFirst("X", href);
+				buffer.append(SPC + anchor + item.getText() + ACLOSE + SPC);
+				notags.append(SPC + item.getText() + SPC);
+			} else {
+				buffer.append(SPC + item.getText());
+				notags.append(SPC + item.getText());
+			}
+		}
+		link.setData(breadCrumbs);
+		link.setText(buffer.toString());
+		
+		if (link.getFont() != null) {
+			Dimension d = FigureUtilities.getStringExtents(notags.toString(), link.getFont());
+			link.setSize(d.width, d.height);
+		}
+	}
+	
+	/**
+	 * Sets the layout width.
+	 * @param widthHint
+	 */
+	public void setLayoutWidth(int widthHint) {
+		breadCrumbGridData.widthHint = widthHint;
+		breadCrumbGridData.minimumWidth = widthHint;
+		groupGridData.widthHint = widthHint;
+		groupGridData.minimumWidth = widthHint;
+		group.setSize(widthHint, group.getSize().y);
+	}
+
+	/////////////////////////////////
+	// Getter/Setter methods
+	/////////////////////////////////
+	
+	/**
+	 * Gets the {@link Group} control.
+	 * @return Group object which contains the link which has the breadcrumb text.
+	 */
+	public Group getGroup() {
+		return group;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.widgets.Composite#layout()
+	 */
+	public void layout() {
+		super.layout();
+		group.layout();
+	}
+	
+	/**
+	 * Returns the {@link Toolbar} control.
+	 * @return ToolBar
+	 */
+	public ToolBar getToolBar() {
+		return toolbar;
+	}
+
+	/**
+	 * Gets the {@link Link} control.
+	 * @return the Link object which has the breadcrumb text
+	 */
+	public Link getLink() {
+		return link;
+	}
+
+	/**
+	 * Gets the number of breadcrumb items.
+	 * @return
+	 */
+	public int getItemCount() {
+		return breadCrumbs.size();
+	}
+	
+	/**
+	 * Sets the separator character to put between breadCrumbs.
+	 * @param separatorChar
+	 */
+	public void setSeparatorChar(char separatorChar) {
+		this.separatorChar = separatorChar;
+	}
+
+	/**
+	 * Sets the title for the group box.
+	 * @param title the title
+	 */
+	public void setTitle(String title) {
+		group.setText((title == null ? "" : title));
+	}
+	
+	/**
+	 * Sets the text for the link.  Not recommended - a better way is to add items.
+	 * @param linkText
+	 */
+	public void setLinkText(String linkText) {
+		link.setText((linkText == null ? "" : linkText));
+	}
+	
+	/**
+	 * Sets the foreground color of the breadcrumb links.
+	 * @param color
+	 */
+	public void setLinkForeground(Color color) {
+		link.setForeground(color);
+	}
+	
+	/**
+	 * Sets the background color of the breadcrumb links.
+	 * @param color
+	 */
+	public void setLinkBackground(Color color) {
+		link.setBackground(color);
+	}
+	
+	/**
+	 * Sets the foreground color of the Group control.
+	 * @param color
+	 */
+	public void setGroupForeground(Color color) {
+		super.setForeground(color);
+		group.setForeground(color);
+	}
+	
+	/**
+	 * Sets the background color of the Group control.
+	 * @param color
+	 */
+	public void setGroupBackground(Color color) {
+		group.setBackground(color);
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/widgets/BreadCrumbHook.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/widgets/BreadCrumbHook.java
new file mode 100644
index 0000000..40e96a9
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/widgets/BreadCrumbHook.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * Copyright 2005-2006, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.widgets;
+
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.mylar.zest.core.messages.ZestUIMessages;
+import org.eclipse.mylar.zest.core.viewers.INestedGraphContentProvider;
+import org.eclipse.mylar.zest.core.viewers.INestedGraphEntityContentProvider;
+import org.eclipse.mylar.zest.core.viewers.INestedGraphFocusChangedListener;
+import org.eclipse.mylar.zest.core.viewers.NestedGraphViewer;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+
+/**
+ * A convenience class for hooking a BreadCrumbBar to a NestedGraphViewer.
+ * @author Del Myers
+ */
+//@tag bug(151889-ViewCoupling)
+public class BreadCrumbHook implements INestedGraphFocusChangedListener, DisposeListener, IBreadCrumbListener {
+
+	private BreadCrumbBar bar;
+	private NestedGraphViewer viewer;
+	//for convenient access.
+	private IContentProvider content;
+	private IBaseLabelProvider label; 
+
+	/**
+	 * Creates a new hook for the given BreadCrumbBar and NestedGraphViewer.
+	 * Expects that the content provider and the label provider for the viewer have
+	 * already been set.
+	 * @param bar the BreadCrumbBar to hook to.
+	 * @param viewer the NestedGraphViewer to hook to.
+	 */
+	public BreadCrumbHook(BreadCrumbBar bar, NestedGraphViewer viewer) {
+		this.bar = bar;
+		this.viewer = viewer;
+		this.content = viewer.getContentProvider();
+		this.label = viewer.getLabelProvider();
+		viewer.getControl().addDisposeListener(this);
+		bar.addDisposeListener(this);
+		hook();
+	}
+	
+	
+	/**
+	 * Unhooks the BreadCrumbHook from the BreadCrumbBar and NestedGraphViewer. Offered
+	 * for robust hooking/unhooking functionality of a BreadCrumbBar. Clients need not
+	 * worry about unhooking by default. The BreadCrumbHook will automatically unhook at
+	 * the end of the viewer and/or bar's lifecycle.
+	 *
+	 */
+	public final void unHook() {
+		if (checkBar()) bar.removeBreadCrumbListener(this);
+		if (checkViewer()) viewer.removeFocusListener(this);
+		
+	}
+	
+	private boolean checkViewer() {
+		return (viewer != null && viewer.getControl() != null && !viewer.getControl().isDisposed());
+	}
+	
+	private boolean checkBar() {
+		return (bar != null && !bar.isDisposed());
+	}
+	/**
+	 * Hooks a previously unhooked BreadCrumbHook. Clients need not worry about hooking
+	 * by default. The BreadCrumbHook is automatically hooked at creation.
+	 *
+	 */
+	public final void hook() {
+		if (!(checkBar() && checkViewer())) return;
+		viewer.addFocusListener(this);
+		bar.addBreadCrumbListener(this);
+		focusChanged(null, viewer.getFocus());
+	}
+	
+	
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.viewers.INestedGraphFocusChangedListener#focusChanged(java.lang.Object, java.lang.Object)
+	 */
+	public void focusChanged(Object oldNode, Object newNode) {
+		bar.clearItems();
+		Object node = newNode;
+		while (node != null) {
+			String text = (label instanceof ILabelProvider) ? ((ILabelProvider)label).getText(node) : "Node";
+			new BreadCrumbItem(bar,0,text, node);
+			node = getParent(node);
+		}
+		String text = ZestUIMessages.VIEW_NESTED_TOP_NODE;
+		new BreadCrumbItem(bar, 0, text, null);
+
+		bar.setBackEnabled(viewer.canGoBackward());
+		bar.setForwardEnabled(viewer.canGoForward());
+		bar.setUpEnabled(viewer.focusHasParent());
+		bar.layout();
+
+	}
+
+	/**
+	 * @param node
+	 * @return
+	 */
+	private Object getParent(Object node) {
+		if (content instanceof INestedGraphContentProvider) {
+			return ((INestedGraphContentProvider)content).getParent(node);
+		} else if (content instanceof INestedGraphEntityContentProvider) {
+			return ((INestedGraphEntityContentProvider)content).getParent(node);
+		}
+		return null;
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
+	 */
+	public void widgetDisposed(DisposeEvent e) {
+		if (e.widget == viewer.getControl()) {
+			if (checkBar()) bar.removeBreadCrumbListener(this);
+		} else if (e.widget == bar) {
+			if (checkViewer()) viewer.removeFocusListener(this);
+		}
+		//get rid of hanging references.
+		if (!(checkBar() || checkViewer())) {
+			viewer = null;
+			bar = null;
+		}
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.widgets.IBreadCrumbListener#breadCrumbSelected(org.eclipse.mylar.zest.core.widgets.BreadCrumbItem)
+	 */
+	public void breadCrumbSelected(BreadCrumbItem item) {
+		viewer.setFocus(item.getData());
+		
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.widgets.IBreadCrumbListener#handleBackButtonSelected()
+	 */
+	public void handleBackButtonSelected() {
+		viewer.goBackward();		
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.widgets.IBreadCrumbListener#handleForwardButtonSelected()
+	 */
+	public void handleForwardButtonSelected() {
+		viewer.goForward();
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.mylar.zest.core.widgets.IBreadCrumbListener#handleUpButtonSelected()
+	 */
+	public void handleUpButtonSelected() {
+		viewer.goUp();		
+	}
+
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/widgets/BreadCrumbItem.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/widgets/BreadCrumbItem.java
new file mode 100644
index 0000000..4c341c8
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/widgets/BreadCrumbItem.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.widgets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Item;
+
+
+/**
+ * An item that gets put into a {@link BreadCrumbBar}.
+ * It contains text to display as a link and a data Object.
+ * 
+ * @author Chris Callendar
+ */
+public class BreadCrumbItem extends Item {
+
+	/**
+	 * Creates a new BreadCrumbItem and adds it to the BreadCrumbBar at the end.
+	 * @param breadCrumbBar	The bar to add this item to.
+	 * @param text	The text to display in the breadcrumb.
+	 * @param data	The data associated with the breadcrumb.
+	 */
+	public BreadCrumbItem(BreadCrumbBar breadCrumbBar, String text, Object data) {
+		this(breadCrumbBar, breadCrumbBar.getItemCount(), text, data);
+	}
+
+	/**
+	 * Creates a new BreadCrumbItem and adds it to the BreadCrumbBar at the given index.
+	 * @param breadCrumbBar	The bar to add this item to.
+	 * @param index	The position in the breadcrumb list to add this into.
+	 * @param text	The text to display in the breadcrumb.
+	 * @param data	The data associated with the breadcrumb.
+	 */
+	public BreadCrumbItem(BreadCrumbBar breadCrumbBar, /*int style,*/ int index, String text, Object data) {
+		super(breadCrumbBar.getGroup(), SWT.NONE, index);
+		setText(text);
+		setData(data);
+		breadCrumbBar.createItem(this, index);
+	}
+	
+}
diff --git a/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/widgets/IBreadCrumbListener.java b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/widgets/IBreadCrumbListener.java
new file mode 100644
index 0000000..90902ae
--- /dev/null
+++ b/visualization/plugins/org.eclipse.mylar.zest.core/src/org/eclipse/mylar/zest/core/widgets/IBreadCrumbListener.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright 2005, CHISEL Group, University of Victoria, Victoria, BC, Canada.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     The Chisel Group, University of Victoria
+ *******************************************************************************/
+package org.eclipse.mylar.zest.core.widgets;
+
+
+/**
+ * A listener for breadcrumb selection events.  When a breadcrumb link is clicked 
+ * an event will be fired.  
+ * 
+ * @author Chris Callendar
+ */
+public interface IBreadCrumbListener {
+
+	/**
+	 * Signals that a breadcrumb has been selected.
+	 * @param item the selected item
+	 */
+	public void breadCrumbSelected(BreadCrumbItem item);
+	
+	/**
+	 * Notifies listeners that the back button was clicked.
+	 */
+	public void handleBackButtonSelected();
+	
+	/**
+	 * Notifies listeners that the forward button was clicked.
+	 */
+	public void handleForwardButtonSelected();
+	
+	/**
+	 * Notifies listeners that the up button was clicked.
+	 */
+	public void handleUpButtonSelected();
+	
+}