re-factoring to separate UI from non-ui plugins
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/.classpath b/2.0/plugins/org.eclipse.epf.common.ui/.classpath
new file mode 100644
index 0000000..751c8f2
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/.project b/2.0/plugins/org.eclipse.epf.common.ui/.project
new file mode 100644
index 0000000..93ce6a0
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.epf.common.ui</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/.settings/org.eclipse.pde.core.prefs b/2.0/plugins/org.eclipse.epf.common.ui/.settings/org.eclipse.pde.core.prefs
new file mode 100644
index 0000000..dda8a84
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/.settings/org.eclipse.pde.core.prefs
@@ -0,0 +1,4 @@
+#Fri Jan 04 15:09:09 PST 2008
+eclipse.preferences.version=1
+pluginProject.extensions=false
+resolve.requirebundle=false
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/META-INF/MANIFEST.MF b/2.0/plugins/org.eclipse.epf.common.ui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..78d2911
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Ui Plug-in
+Bundle-SymbolicName: org.eclipse.epf.common.ui
+Bundle-Version: 1.0.0
+Bundle-Activator: org.eclipse.epf.common.ui.CommonUIPlugin
+Import-Package: org.osgi.framework;version="1.3.0"
+Eclipse-LazyStart: true
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.epf.common
+Export-Package: org.eclipse.epf.common.ui,
+ org.eclipse.epf.common.ui.util
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/build.properties b/2.0/plugins/org.eclipse.epf.common.ui/build.properties
new file mode 100644
index 0000000..34d2e4d
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/AbstractPlugin.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/AbstractPlugin.java
new file mode 100644
index 0000000..f50e91f
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/AbstractPlugin.java
@@ -0,0 +1,76 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2007 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 implementation
+//------------------------------------------------------------------------------
+package org.eclipse.epf.common.ui;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.epf.common.AbstractActivator;
+import org.eclipse.epf.common.ui.util.MsgDialog;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * The abstract base class for all EPF plug-ins.
+ * 
+ * @author Kelvin Low
+ * @author Jinhua Xi
+ * @since 1.0
+ */
+public abstract class AbstractPlugin extends AbstractActivator {
+
+	// The message dialog hash map.
+	private static Map<String, MsgDialog> msgDialogs = new HashMap<String, MsgDialog>();
+
+	/**
+	 * Default constructor.
+	 */
+	public AbstractPlugin() {
+		super();
+	}
+
+	/**
+	 * Returns the message dialog given the plug-in ID.
+	 * 
+	 * @return The new or cached message dialog.
+	 */
+	public MsgDialog getMsgDialog(AbstractActivator plugin) {
+		MsgDialog msgDialog = (MsgDialog) msgDialogs.get(plugin.getId());
+		if (msgDialog == null) {
+			msgDialog = new MsgDialog(plugin, getWorkbench().getDisplay().getActiveShell());
+			msgDialogs.put(plugin.getId(), msgDialog);
+		}
+		return msgDialog;
+	}
+
+	
+	public MsgDialog getMsgDialog() {		
+		MsgDialog msgDialog = (MsgDialog) msgDialogs.get(getId());
+		if (msgDialog == null) {
+			msgDialog = new MsgDialog(this);
+			msgDialogs.put(getId(), msgDialog);
+		}
+		return msgDialog;
+	}
+	
+	/**
+	 * Returns the standard display to be used. The method first checks, if the
+	 * thread calling this method has an associated disaply. If so, this display
+	 * is returned. Otherwise the method returns the default display.
+	 */
+	public static Display getStandardDisplay() {
+		Display display;
+		display = Display.getCurrent();
+		if (display == null)
+			display = Display.getDefault();
+		return display;
+	}
+
+}
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/CommonUIPlugin.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/CommonUIPlugin.java
new file mode 100644
index 0000000..6eadc3e
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/CommonUIPlugin.java
@@ -0,0 +1,58 @@
+package org.eclipse.epf.common.ui;
+
+import org.eclipse.epf.common.CommonPlugin;
+import org.eclipse.epf.common.IMessageCallback;
+import org.eclipse.epf.common.ui.util.MsgBox;
+import org.osgi.framework.BundleContext;
+
+public class CommonUIPlugin extends AbstractPlugin {
+
+	// The shared plug-in instance.
+	private static CommonUIPlugin plugin;
+
+	/**
+	 * Creates a new instance.
+	 */
+	public CommonUIPlugin() {
+		super();
+		plugin = this;
+	}
+
+	/**
+	 * @see org.eclipse.epf.common.ui.AbstractPlugin#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+		
+//		// set the preference store for the common plugin
+//		PreferenceStoreWrapper storeWrapper = new PreferenceStoreWrapper(getPreferenceStore());
+//		CommonPlugin.getDefault().setPreferenceStore(storeWrapper);
+		
+		// create the message callback context for the non-ui plugins
+		// this is the context for message callback
+		// for eclipse client, this is the Shell object
+		CommonPlugin.getDefault().setContext(MsgBox.getDefaultShell());
+
+		// create the MessageCallback to be accessible to the non-ui plugin
+		IMessageCallback msgCallback = new MessageCallback();
+	}
+
+	/**
+	 * @see org.eclipse.epf.common.ui.AbstractPlugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		super.stop(context);
+		plugin = null;
+	}
+
+	/**
+	 * Gets the shared instance.
+	 * 
+	 * @return the shared plug-in instance
+	 */
+	public static CommonUIPlugin getDefault() {
+		return plugin;
+	}
+
+
+}
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/MessageCallback.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/MessageCallback.java
new file mode 100644
index 0000000..fb9a5d3
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/MessageCallback.java
@@ -0,0 +1,42 @@
+package org.eclipse.epf.common.ui;
+
+import org.eclipse.epf.common.AbstractActivator;
+import org.eclipse.epf.common.IMessageCallback;
+import org.eclipse.epf.common.ui.util.MsgDialog;
+
+public class MessageCallback implements IMessageCallback {
+
+	public void displayWarning(AbstractActivator plugin, String title, String msg, String reason) {
+		displayWarning(plugin, title, msg, reason, null, null);		
+	}
+	
+	public void displayWarning(AbstractActivator plugin, String msg, String reason, Throwable ex) {
+		displayWarning(plugin, msg, reason, null, ex);
+	}
+
+	public void displayWarning(AbstractActivator plugin, String msg, String reason,
+			String details, Throwable ex) {
+		String title = CommonUIPlugin.getDefault().getWorkbench().getDisplay().getActiveShell().getText();
+		displayWarning(plugin, title, msg, reason, details, ex);
+	}
+	
+	public void displayWarning(AbstractActivator plugin, String title, String msg, String reason,
+			String details, Throwable ex) {
+		MsgDialog dlg = CommonUIPlugin.getDefault().getMsgDialog(plugin);
+		dlg.displayWarning(title, msg, reason, details, ex);
+	}
+	
+	public void displayError(AbstractActivator plugin, String title, String msg) {
+		displayError(plugin, title, msg, null, null, null);
+	}
+	
+	public void displayError(AbstractActivator plugin, String title, String msg, Throwable ex) {
+		displayError(plugin, title, msg, null, null, ex);
+	}
+	public void displayError(AbstractActivator plugin, String title, String msg, String reason, String details, Throwable ex) {
+		MsgDialog dlg = CommonUIPlugin.getDefault().getMsgDialog(plugin);
+		dlg.displayError(title, msg, reason, details, ex);
+
+	}
+
+}
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/PreferenceStoreWrapper.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/PreferenceStoreWrapper.java
new file mode 100644
index 0000000..912c84f
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/PreferenceStoreWrapper.java
@@ -0,0 +1,477 @@
+package org.eclipse.epf.common.ui;
+
+import org.eclipse.epf.common.preferences.IPreferenceStoreWrapper;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+public class PreferenceStoreWrapper implements IPreferenceStoreWrapper {
+	private IPreferenceStore store;
+	public PreferenceStoreWrapper(IPreferenceStore store) {
+		this.store = store;
+	}
+	
+	   /**
+     * Returns the current value of the boolean-valued preference with the
+     * given name.
+     * Returns the default-default value (<code>false</code>) if there
+     * is no preference with the given name, or if the current value 
+     * cannot be treated as a boolean.
+     *
+     * @param name the name of the preference
+     * @return the boolean-valued preference
+     */
+    public boolean getBoolean(String name) {
+    	return store.getBoolean(name);
+    }
+
+    /**
+     * Returns the default value for the boolean-valued preference
+     * with the given name.
+     * Returns the default-default value (<code>false</code>) if there
+     * is no default preference with the given name, or if the default 
+     * value cannot be treated as a boolean.
+     *
+     * @param name the name of the preference
+     * @return the default value of the named preference
+     */
+    public boolean getDefaultBoolean(String name) {
+    	return store.getDefaultBoolean(name);
+    }
+
+    /**
+     * Returns the default value for the double-valued preference
+     * with the given name.
+     * Returns the default-default value (<code>0.0</code>) if there
+     * is no default preference with the given name, or if the default 
+     * value cannot be treated as a double.
+     *
+     * @param name the name of the preference
+     * @return the default value of the named preference
+     */
+    public double getDefaultDouble(String name) {
+    	return store.getDefaultDouble(name);
+    }
+
+    /**
+     * Returns the default value for the float-valued preference
+     * with the given name.
+     * Returns the default-default value (<code>0.0f</code>) if there
+     * is no default preference with the given name, or if the default 
+     * value cannot be treated as a float.
+     *
+     * @param name the name of the preference
+     * @return the default value of the named preference
+     */
+    public float getDefaultFloat(String name) {
+    	return store.getDefaultFloat(name);
+    }
+
+    /**
+     * Returns the default value for the integer-valued preference
+     * with the given name.
+     * Returns the default-default value (<code>0</code>) if there
+     * is no default preference with the given name, or if the default 
+     * value cannot be treated as an integer.
+     *
+     * @param name the name of the preference
+     * @return the default value of the named preference
+     */
+    public int getDefaultInt(String name) {
+    	return store.getDefaultInt(name);
+    }
+
+    /**
+     * Returns the default value for the long-valued preference
+     * with the given name.
+     * Returns the default-default value (<code>0L</code>) if there
+     * is no default preference with the given name, or if the default 
+     * value cannot be treated as a long.
+     *
+     * @param name the name of the preference
+     * @return the default value of the named preference
+     */
+    public long getDefaultLong(String name) {
+    	return store.getDefaultLong(name);
+    }
+
+    /**
+     * Returns the default value for the string-valued preference
+     * with the given name.
+     * Returns the default-default value (the empty string <code>""</code>) 
+     * is no default preference with the given name, or if the default 
+     * value cannot be treated as a string.
+     *
+     * @param name the name of the preference
+     * @return the default value of the named preference
+     */
+    public String getDefaultString(String name) {
+    	return store.getDefaultString(name);
+    }
+
+    /**
+     * Returns the current value of the double-valued preference with the
+     * given name.
+     * Returns the default-default value (<code>0.0</code>) if there
+     * is no preference with the given name, or if the current value 
+     * cannot be treated as a double.
+     *
+     * @param name the name of the preference
+     * @return the double-valued preference
+     */
+    public double getDouble(String name) {
+    	return store.getDouble(name);
+    }
+
+    /**
+     * Returns the current value of the float-valued preference with the
+     * given name.
+     * Returns the default-default value (<code>0.0f</code>) if there
+     * is no preference with the given name, or if the current value 
+     * cannot be treated as a float.
+     *
+     * @param name the name of the preference
+     * @return the float-valued preference
+     */
+    public float getFloat(String name) {
+    	return store.getFloat(name);
+    }
+
+    /**
+     * Returns the current value of the integer-valued preference with the
+     * given name.
+     * Returns the default-default value (<code>0</code>) if there
+     * is no preference with the given name, or if the current value 
+     * cannot be treated as an integter.
+     *
+     * @param name the name of the preference
+     * @return the int-valued preference
+     */
+    public int getInt(String name) {
+    	return store.getInt(name);
+    }
+
+    /**
+     * Returns the current value of the long-valued preference with the
+     * given name.
+     * Returns the default-default value (<code>0L</code>) if there
+     * is no preference with the given name, or if the current value 
+     * cannot be treated as a long.
+     *
+     * @param name the name of the preference
+     * @return the long-valued preference
+     */
+    public long getLong(String name) {
+    	return store.getLong(name);
+    }
+
+    /**
+     * Returns the current value of the string-valued preference with the
+     * given name.
+     * Returns the default-default value (the empty string <code>""</code>)
+     * if there is no preference with the given name, or if the current value 
+     * cannot be treated as a string.
+     *
+     * @param name the name of the preference
+     * @return the string-valued preference
+     */
+    public String getString(String name) {
+    	return store.getString(name);
+    }
+
+    /**
+     * Returns whether the current value of the preference with the given name
+     * has the default value.
+     *
+     * @param name the name of the preference
+     * @return <code>true</code> if the preference has a known default value
+     * and its current value is the same, and <code>false</code> otherwise
+     * (including the case where the preference is unknown to this store)
+     */
+    public boolean isDefault(String name) {
+    	return store.isDefault(name);
+    }
+
+    /**
+     * Returns whether the current values in this property store
+     * require saving.
+     *
+     * @return <code>true</code> if at least one of values of 
+     *  the preferences known to this store has changed and 
+     *  requires saving, and <code>false</code> otherwise.
+     */
+    public boolean needsSaving() {
+    	return store.needsSaving();
+    }
+
+    /**
+     * Sets the current value of the preference with the given name to
+     * the given string value without sending a property change.
+     * <p>
+     * This method does not fire a property change event and 
+     * should only be used for setting internal preferences 
+     * that are not meant to be processed by listeners.
+     * Normal clients should instead call #setValue.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param value the new current value of the preference
+     */
+    public void putValue(String name, String value) {
+    	store.putValue(name, value);
+    }
+
+    /**
+     * Sets the default value for the double-valued preference with the
+     * given name. 
+     * <p>
+     * Note that the current value of the preference is affected if
+     * the preference's current value was its old default value, in which
+     * case it changes to the new default value. If the preference's current
+     * is different from its old default value, its current value is
+     * unaffected. No property change events are reported by changing default
+     * values.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param value the new default value for the preference
+     */
+    public void setDefault(String name, double value) {
+    	setDefault(name, value);
+    }
+
+    /**
+     * Sets the default value for the float-valued preference with the
+     * given name. 
+     * <p>
+     * Note that the current value of the preference is affected if
+     * the preference's current value was its old default value, in which
+     * case it changes to the new default value. If the preference's current
+     * is different from its old default value, its current value is
+     * unaffected. No property change events are reported by changing default
+     * values.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param value the new default value for the preference
+     */
+    public void setDefault(String name, float value) {
+       	setDefault(name, value);
+    }
+
+    /**
+     * Sets the default value for the integer-valued preference with the
+     * given name. 
+     * <p>
+     * Note that the current value of the preference is affected if
+     * the preference's current value was its old default value, in which
+     * case it changes to the new default value. If the preference's current
+     * is different from its old default value, its current value is
+     * unaffected. No property change events are reported by changing default
+     * values.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param value the new default value for the preference
+     */
+    public void setDefault(String name, int value) {
+       	setDefault(name, value);
+    }
+
+    /**
+     * Sets the default value for the long-valued preference with the
+     * given name. 
+     * <p>
+     * Note that the current value of the preference is affected if
+     * the preference's current value was its old default value, in which
+     * case it changes to the new default value. If the preference's current
+     * is different from its old default value, its current value is
+     * unaffected. No property change events are reported by changing default
+     * values.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param value the new default value for the preference
+     */
+    public void setDefault(String name, long value) {
+       	setDefault(name, value);
+    }
+
+    /**
+     * Sets the default value for the string-valued preference with the
+     * given name. 
+     * <p>
+     * Note that the current value of the preference is affected if
+     * the preference's current value was its old default value, in which
+     * case it changes to the new default value. If the preference's current
+     * is different from its old default value, its current value is
+     * unaffected. No property change events are reported by changing default
+     * values.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param defaultObject the new default value for the preference
+     */
+    public void setDefault(String name, String defaultObject) {
+    	setDefault(name, defaultObject);
+    }
+
+    /**
+     * Sets the default value for the boolean-valued preference with the
+     * given name. 
+     * <p>
+     * Note that the current value of the preference is affected if
+     * the preference's current value was its old default value, in which
+     * case it changes to the new default value. If the preference's current
+     * is different from its old default value, its current value is
+     * unaffected. No property change events are reported by changing default
+     * values.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param value the new default value for the preference
+     */
+    public void setDefault(String name, boolean value) {
+       	setDefault(name, value);
+    }
+
+    /**
+     * Sets the current value of the preference with the given name back
+     * to its default value.
+     * <p>
+     * Note that the preferred way of re-initializing a preference to the
+     * appropriate default value is to call <code>setToDefault</code>.
+     * This is implemented by removing the named value from the store, 
+     * thereby exposing the default value.
+     * </p>
+     *
+     * @param name the name of the preference
+     */
+    public void setToDefault(String name) {
+       	setToDefault(name);
+    }
+
+    /**
+     * Sets the current value of the double-valued preference with the
+     * given name.
+     * <p>
+     * A property change event is reported if the current value of the 
+     * preference actually changes from its previous value. In the event
+     * object, the property name is the name of the preference, and the
+     * old and new values are wrapped as objects.
+     * </p>
+     * <p>
+     * Note that the preferred way of re-initializing a preference to its
+     * default value is to call <code>setToDefault</code>.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param value the new current value of the preference
+     */
+    public void setValue(String name, double value) {
+    	setValue(name, value);
+    }
+
+    /**
+     * Sets the current value of the float-valued preference with the
+     * given name.
+     * <p>
+     * A property change event is reported if the current value of the 
+     * preference actually changes from its previous value. In the event
+     * object, the property name is the name of the preference, and the
+     * old and new values are wrapped as objects.
+     * </p>
+     * <p>
+     * Note that the preferred way of re-initializing a preference to its
+     * default value is to call <code>setToDefault</code>.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param value the new current value of the preference
+     */
+    public void setValue(String name, float value) {
+    	setValue(name, value);
+    }
+
+    /**
+     * Sets the current value of the integer-valued preference with the
+     * given name.
+     * <p>
+     * A property change event is reported if the current value of the 
+     * preference actually changes from its previous value. In the event
+     * object, the property name is the name of the preference, and the
+     * old and new values are wrapped as objects.
+     * </p>
+     * <p>
+     * Note that the preferred way of re-initializing a preference to its
+     * default value is to call <code>setToDefault</code>.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param value the new current value of the preference
+     */
+    public void setValue(String name, int value) {
+    	setValue(name, value);
+    }
+
+    /**
+     * Sets the current value of the long-valued preference with the
+     * given name.
+     * <p>
+     * A property change event is reported if the current value of the 
+     * preference actually changes from its previous value. In the event
+     * object, the property name is the name of the preference, and the
+     * old and new values are wrapped as objects.
+     * </p>
+     * <p>
+     * Note that the preferred way of re-initializing a preference to its
+     * default value is to call <code>setToDefault</code>.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param value the new current value of the preference
+     */
+    public void setValue(String name, long value) {
+    	setValue(name, value);
+    }
+
+    /**
+     * Sets the current value of the string-valued preference with the
+     * given name.
+     * <p>
+     * A property change event is reported if the current value of the 
+     * preference actually changes from its previous value. In the event
+     * object, the property name is the name of the preference, and the
+     * old and new values are wrapped as objects.
+     * </p>
+     * <p>
+     * Note that the preferred way of re-initializing a preference to its
+     * default value is to call <code>setToDefault</code>.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param value the new current value of the preference
+     */
+    public void setValue(String name, String value) {
+    	setValue(name, value);
+    }
+
+    /**
+     * Sets the current value of the boolean-valued preference with the
+     * given name.
+     * <p>
+     * A property change event is reported if the current value of the 
+     * preference actually changes from its previous value. In the event
+     * object, the property name is the name of the preference, and the
+     * old and new values are wrapped as objects.
+     * </p>
+     * <p>
+     * Note that the preferred way of re-initializing a preference to its
+     * default value is to call <code>setToDefault</code>.
+     * </p>
+     *
+     * @param name the name of the preference
+     * @param value the new current value of the preference
+     */
+    public void setValue(String name, boolean value) {
+    	setValue(name, value);
+    }
+}
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ClipboardUtil.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ClipboardUtil.java
new file mode 100644
index 0000000..2abf026
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ClipboardUtil.java
@@ -0,0 +1,113 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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 implementation
+//------------------------------------------------------------------------------
+package org.eclipse.epf.common.ui.util;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.epf.common.utils.FileUtil;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.HTMLTransfer;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Display;
+import org.osgi.framework.Bundle;
+
+/**
+ * Utility class for retrieving data from the clipboard.
+ * 
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class ClipboardUtil {
+	
+	/**
+	 * The current clipboard.
+	 */
+	private static Clipboard clipboard;
+
+	private static final String SOURCE_URL = "SourceURL:"; //$NON-NLS-1$
+
+	private static Transfer htmlTransfer = null;
+
+	static {
+		if (SWT.getPlatform().equals("win32")) { //$NON-NLS-1$
+			try {
+				Bundle bundle = Platform
+						.getBundle("org.eclipse.epf.common.win32.win32.x86"); //$NON-NLS-1$
+				Class c = bundle
+						.loadClass("org.eclipse.epf.common.win32.Win32HTMLTransfer"); //$NON-NLS-1$
+				if (c != null) {
+					htmlTransfer = (Transfer) c.newInstance();
+				}
+			} catch (Exception e) {
+				htmlTransfer = null;
+			}
+		}
+	}
+
+	/**
+	 * Gets the HTML source URL from the current clipboard.
+	 * 
+	 * @return the HTML source URL or <code>null</code>
+	 */
+	public static String getHTMLSourceURL() {
+		if (htmlTransfer == null) {
+			return null;
+		}
+
+		Clipboard clipboard = new Clipboard(Display.getCurrent());
+		String sourceURL = null;
+		try {
+			String htmlContent = (String) clipboard.getContents(htmlTransfer);
+			if (htmlContent != null && htmlContent.length() > 0) {
+				int index = htmlContent.indexOf(SOURCE_URL);
+				if (index > 0) {
+					sourceURL = htmlContent.substring(index
+							+ SOURCE_URL.length());
+					sourceURL = sourceURL.substring(0, sourceURL
+							.indexOf(FileUtil.LINE_SEP));
+				}
+			}
+			if (sourceURL != null && sourceURL.indexOf("\\") != -1) { //$NON-NLS-1$
+				// IE provides sourceURL in form "file://C:\foo\bar.htm"
+				// but when the hrefs are resolved, files look like "file:///C:/foo/bar.htm"
+				URL url = new URL(sourceURL);
+				sourceURL = url.toExternalForm();
+				if (sourceURL.startsWith("file://") && !sourceURL.startsWith("file:///")) { //$NON-NLS-1$ //$NON-NLS-2$
+					// need to add a third / so rte.js can match the sourceURL to hrefs
+					sourceURL = "file:///" + sourceURL.substring(7); //$NON-NLS-1$
+				}
+			}
+			return sourceURL;
+		} catch (MalformedURLException urlEx) {
+			return sourceURL;
+		} finally {
+			clipboard.dispose();
+		}
+	}
+
+	/**
+	 * Copy the string to the clipboard.
+	 */
+	public static void copyTextHTMLToClipboard(String string) {
+		if (clipboard != null)
+			clipboard.dispose();
+		clipboard = new Clipboard(null);
+		clipboard.setContents(new Object[] { string, string },
+				new Transfer[] { TextTransfer.getInstance(), HTMLTransfer.getInstance() });
+		if (clipboard != null)
+			clipboard.dispose();
+	}
+
+}
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/CommonPreferences.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/CommonPreferences.java
new file mode 100644
index 0000000..867c630
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/CommonPreferences.java
@@ -0,0 +1,50 @@
+package org.eclipse.epf.common.ui.util;
+
+import org.eclipse.epf.common.ui.CommonUIPlugin;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * Manages the common preferences.
+ * 
+ * @author Kelvin Low
+ * @since 1.2
+ */
+public class CommonPreferences {
+
+	/**
+	 * Preference key for storing the preference history size.
+	 */
+	private static final String PREFERENCE_HISTORY_SIZE = "preferenceHistorySize"; //$NON-NLS-1$
+
+	// The plug-in specific preference store.
+	private static IPreferenceStore prefStore = CommonUIPlugin.getDefault()
+			.getPreferenceStore();
+
+	static {
+		// Initialize the default preference values.
+		prefStore.setDefault(PREFERENCE_HISTORY_SIZE,
+				getDefaultPreferenceHistorySize());
+	}
+
+	/**
+	 * Gets the default preference history size.
+	 */
+	public static int getDefaultPreferenceHistorySize() {
+		return 10;
+	}
+
+	/**
+	 * Gets the preference history size.
+	 */
+	public static int getPreferenceHistorySize() {
+		return prefStore.getInt(PREFERENCE_HISTORY_SIZE);
+	}
+
+	/**
+	 * Saves the preference history size.
+	 */
+	public static void setPreferenceHistorySize(int value) {
+		prefStore.setValue(PREFERENCE_HISTORY_SIZE, value);
+	}
+
+}
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ErrorDialogNoReason.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ErrorDialogNoReason.java
new file mode 100644
index 0000000..a1271c6
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/ErrorDialogNoReason.java
@@ -0,0 +1,598 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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 implementation
+//------------------------------------------------------------------------------
+package org.eclipse.epf.common.ui.util;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IconAndMessageDialog;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Displays an error dialog without the Details button.
+ * 
+ * @author Bingxue Xu
+ * @since 1.0
+ */
+public class ErrorDialogNoReason extends IconAndMessageDialog {
+
+	/**
+	 * Static to prevent opening of error dialogs for automated testing.
+	 */
+	public static final boolean AUTOMATED_MODE = false;
+
+	/**
+	 * Reserve room for this many list items.
+	 */
+	private static final int LIST_ITEM_COUNT = 7;
+
+	/**
+	 * The nesting indent.
+	 */
+	private static final String NESTING_INDENT = "  "; //$NON-NLS-1$
+
+	/**
+	 * The Details button.
+	 */
+	protected Button detailsButton;
+
+	/**
+	 * The title of the dialog.
+	 */
+	private String title;
+
+	/**
+	 * The SWT list control that displays the error details.
+	 */
+	private List list;
+
+	/**
+	 * Indicates whether the error details viewer is currently created.
+	 */
+	private boolean listCreated = false;
+
+	/**
+	 * Filter mask for determining which status items to display.
+	 */
+	private int displayMask = 0xFFFF;
+
+	/**
+	 * The main status object.
+	 */
+	private IStatus status;
+
+	/**
+	 * The current clipboard. To be disposed when closing the dialog.
+	 */
+	private Clipboard clipboard;
+
+	private boolean shouldIncludeTopLevelErrorInDetails = false;
+
+	/**
+	 * Creates an error dialog. Note that the dialog will have no visual
+	 * representation (no widgets) until it is told to open.
+	 * <p>
+	 * Normally one should use <code>openError</code> to create and open one
+	 * of these. This constructor is useful only if the error object being
+	 * displayed contains child items <it>and </it> you need to specify a mask
+	 * which will be used to filter the displaying of these children.
+	 * </p>
+	 * 
+	 * @param parentShell
+	 *            the shell under which to create this dialog
+	 * @param dialogTitle
+	 *            the title to use for this dialog, or <code>null</code> to
+	 *            indicate that the default title should be used
+	 * @param message
+	 *            the message to show in this dialog, or <code>null</code> to
+	 *            indicate that the error's message should be shown as the
+	 *            primary message
+	 * @param status
+	 *            the error to show to the user
+	 * @param displayMask
+	 *            the mask to use to filter the displaying of child items, as
+	 *            per <code>IStatus.matches</code>
+	 * @see org.eclipse.core.runtime.IStatus#matches(int)
+	 */
+	public ErrorDialogNoReason(Shell parentShell, String dialogTitle,
+			String message, IStatus status, int displayMask) {
+		super(parentShell);
+		this.title = dialogTitle == null ? JFaceResources
+				.getString("Problem_Occurred") : //$NON-NLS-1$
+				dialogTitle;
+		this.message = message == null ? status.getMessage() : message; 
+		this.status = status;
+		this.displayMask = displayMask;
+		setShellStyle(getShellStyle() | SWT.RESIZE);
+	}
+
+	/*
+	 * (non-Javadoc) Method declared on Dialog. Handles the pressing of the Ok
+	 * or Details button in this dialog. If the Ok button was pressed then close
+	 * this dialog. If the Details button was pressed then toggle the displaying
+	 * of the error details area. Note that the Details button will only be
+	 * visible if the error being displayed specifies child details.
+	 */
+	protected void buttonPressed(int id) {
+		if (id == IDialogConstants.DETAILS_ID) {
+			// was the details button pressed?
+			toggleDetailsArea();
+		} else {
+			super.buttonPressed(id);
+		}
+	}
+
+	/*
+	 * (non-Javadoc) Method declared in Window.
+	 */
+	protected void configureShell(Shell shell) {
+		super.configureShell(shell);
+		shell.setText(title);
+	}
+
+	/*
+	 * (non-Javadoc) Method declared on Dialog.
+	 */
+	protected void createButtonsForButtonBar(Composite parent) {
+		// create OK and Details buttons
+		createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
+				true);
+		createButton(parent, IDialogConstants.CANCEL_ID,
+				IDialogConstants.CANCEL_LABEL, false);
+		if (shouldShowDetailsButton()) {
+			detailsButton = createButton(parent, IDialogConstants.DETAILS_ID,
+					IDialogConstants.SHOW_DETAILS_LABEL, false);
+		}
+	}
+
+	/**
+	 * This implementation of the <code>Dialog</code> framework method creates
+	 * and lays out a composite and calls <code>createMessageArea</code> and
+	 * <code>createCustomArea</code> to populate it. Subclasses should
+	 * override <code>createCustomArea</code> to add contents below the
+	 * message.
+	 */
+	protected Control createDialogArea(Composite parent) {
+		createMessageArea(parent);
+		// create a composite with standard margins and spacing
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout();
+		layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+		layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+		layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+		layout.numColumns = 2;
+		composite.setLayout(layout);
+		GridData childData = new GridData(GridData.FILL_BOTH);
+		childData.horizontalSpan = 2;
+		composite.setLayoutData(childData);
+		composite.setFont(parent.getFont());
+		return composite;
+	}
+
+	/*
+	 * @see IconAndMessageDialog#createDialogAndButtonArea(Composite)
+	 */
+	protected void createDialogAndButtonArea(Composite parent) {
+		super.createDialogAndButtonArea(parent);
+		if (this.dialogArea instanceof Composite) {
+			// Create a label if there are no children to force a smaller layout
+			Composite dialogComposite = (Composite) dialogArea;
+			if (dialogComposite.getChildren().length == 0)
+				new Label(dialogComposite, SWT.NULL);
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.dialogs.IconAndMessageDialog#getImage()
+	 */
+	protected Image getImage() {
+		if (status != null) {
+			if (status.getSeverity() == IStatus.WARNING)
+				return getWarningImage();
+			if (status.getSeverity() == IStatus.INFO)
+				return getInfoImage();
+		}
+		// If it was not a warning or an error then return the error image
+		return getErrorImage();
+	}
+
+	/**
+	 * Create this dialog's drop-down list component.
+	 * 
+	 * @param parent
+	 *            the parent composite
+	 * @return the drop-down list component
+	 */
+	protected List createDropDownList(Composite parent) {
+		// create the list
+		list = new List(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL
+				| SWT.MULTI);
+		// fill the list
+		populateList(list);
+		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+				| GridData.GRAB_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL
+				| GridData.GRAB_VERTICAL);
+		data.heightHint = list.getItemHeight() * LIST_ITEM_COUNT;
+		data.horizontalSpan = 2;
+		list.setLayoutData(data);
+		list.setFont(parent.getFont());
+		Menu copyMenu = new Menu(list);
+		MenuItem copyItem = new MenuItem(copyMenu, SWT.NONE);
+		copyItem.addSelectionListener(new SelectionListener() {
+			/*
+			 * @see SelectionListener.widgetSelected (SelectionEvent)
+			 */
+			public void widgetSelected(SelectionEvent e) {
+				copyToClipboard();
+			}
+
+			/*
+			 * @see SelectionListener.widgetDefaultSelected(SelectionEvent)
+			 */
+			public void widgetDefaultSelected(SelectionEvent e) {
+				copyToClipboard();
+			}
+		});
+		copyItem.setText(JFaceResources.getString("copy")); //$NON-NLS-1$
+		list.setMenu(copyMenu);
+		listCreated = true;
+		return list;
+	}
+
+	/*
+	 * (non-Javadoc) Method declared on Window.
+	 */
+	/**
+	 * Extends <code>Window.open()</code>. Opens an error dialog to display
+	 * the error. If you specified a mask to filter the displaying of these
+	 * children, the error dialog will only be displayed if there is at least
+	 * one child status matching the mask.
+	 */
+	public int open() {
+		if (!AUTOMATED_MODE && shouldDisplay(status, displayMask)) {
+			return super.open();
+		}
+		setReturnCode(OK);
+		return OK;
+	}
+
+	/**
+	 * Opens an error dialog to display the given error. Use this method if the
+	 * error object being displayed does not contain child items, or if you wish
+	 * to display all such items without filtering.
+	 * 
+	 * @param parent
+	 *            the parent shell of the dialog, or <code>null</code> if none
+	 * @param dialogTitle
+	 *            the title to use for this dialog, or <code>null</code> to
+	 *            indicate that the default title should be used
+	 * @param message
+	 *            the message to show in this dialog, or <code>null</code> to
+	 *            indicate that the error's message should be shown as the
+	 *            primary message
+	 * @param status
+	 *            the error to show to the user
+	 * @return the code of the button that was pressed that resulted in this
+	 *         dialog closing. This will be <code>Dialog.OK</code> if the OK
+	 *         button was pressed, or <code>Dialog.CANCEL</code> if this
+	 *         dialog's close window decoration or the ESC key was used.
+	 */
+	public static int openError(Shell parent, String dialogTitle,
+			String message, IStatus status) {
+		return openError(parent, dialogTitle, message, status, IStatus.OK
+				| IStatus.INFO | IStatus.WARNING | IStatus.ERROR);
+	}
+
+	/**
+	 * Opens an error dialog to display the given error. Use this method if the
+	 * error object being displayed contains child items <it>and </it> you wish
+	 * to specify a mask which will be used to filter the displaying of these
+	 * children. The error dialog will only be displayed if there is at least
+	 * one child status matching the mask.
+	 * 
+	 * @param parentShell
+	 *            the parent shell of the dialog, or <code>null</code> if none
+	 * @param title
+	 *            the title to use for this dialog, or <code>null</code> to
+	 *            indicate that the default title should be used
+	 * @param message
+	 *            the message to show in this dialog, or <code>null</code> to
+	 *            indicate that the error's message should be shown as the
+	 *            primary message
+	 * @param status
+	 *            the error to show to the user
+	 * @param displayMask
+	 *            the mask to use to filter the displaying of child items, as
+	 *            per <code>IStatus.matches</code>
+	 * @return the code of the button that was pressed that resulted in this
+	 *         dialog closing. This will be <code>Dialog.OK</code> if the OK
+	 *         button was pressed, or <code>Dialog.CANCEL</code> if this
+	 *         dialog's close window decoration or the ESC key was used.
+	 * @see org.eclipse.core.runtime.IStatus#matches(int)
+	 */
+	public static int openError(Shell parentShell, String title,
+			String message, IStatus status, int displayMask) {
+		ErrorDialogNoReason dialog = new ErrorDialogNoReason(parentShell,
+				title, message, status, displayMask);
+		return dialog.open();
+	}
+
+	/**
+	 * Populates the list using this error dialog's status object. This walks
+	 * the child static of the status object and displays them in a list. The
+	 * format for each entry is status_path : status_message If the status's
+	 * path was null then it (and the colon) are omitted.
+	 * 
+	 * @param listToPopulate
+	 *            The list to fill.
+	 */
+	private void populateList(List listToPopulate) {
+		populateList(listToPopulate, status, 0,
+				shouldIncludeTopLevelErrorInDetails);
+	}
+
+	/**
+	 * Populate the list with the messages from the given status. Traverse the
+	 * children of the status deeply and also traverse CoreExceptions that
+	 * appear in the status.
+	 * 
+	 * @param listToPopulate
+	 *            the list to populate
+	 * @param buildingStatus
+	 *            the status being displayed
+	 * @param nesting
+	 *            the nesting level (increases one level for each level of
+	 *            children)
+	 * @param includeStatus
+	 *            whether to include the buildingStatus in the display or just
+	 *            its children
+	 */
+	private void populateList(List listToPopulate, IStatus buildingStatus,
+			int nesting, boolean includeStatus) {
+
+		if (!buildingStatus.matches(displayMask)) {
+			return;
+		}
+
+		Throwable t = buildingStatus.getException();
+		boolean isCoreException = t instanceof CoreException;
+		boolean incrementNesting = false;
+
+		if (includeStatus) {
+			StringBuffer sb = new StringBuffer();
+			for (int i = 0; i < nesting; i++) {
+				sb.append(NESTING_INDENT); 
+			}
+			String message = buildingStatus.getMessage();
+			sb.append(message);
+			listToPopulate.add(sb.toString());
+			incrementNesting = true;
+		}
+
+		if (!isCoreException && t != null) {
+			// Include low-level exception message
+			StringBuffer sb = new StringBuffer();
+			for (int i = 0; i < nesting; i++) {
+				sb.append(NESTING_INDENT); 
+			}
+			String message = t.getLocalizedMessage();
+			if (message == null)
+				message = t.toString();
+
+			sb.append(message);
+			listToPopulate.add(sb.toString());
+			incrementNesting = true;
+		}
+
+		if (incrementNesting)
+			nesting++;
+
+		// Look for a nested core exception
+		if (isCoreException) {
+			CoreException ce = (CoreException) t;
+			IStatus eStatus = ce.getStatus();
+			// Only print the exception message if it is not contained in the
+			// parent message
+			if (message == null || message.indexOf(eStatus.getMessage()) == -1) {
+				populateList(listToPopulate, eStatus, nesting, true);
+			}
+		}
+
+		// Look for child status
+		IStatus[] children = buildingStatus.getChildren();
+		for (int i = 0; i < children.length; i++) {
+			populateList(listToPopulate, children[i], nesting, true);
+		}
+	}
+
+	/**
+	 * Returns whether the given status object should be displayed.
+	 * 
+	 * @param status
+	 *            a status object
+	 * @param mask
+	 *            a mask as per <code>IStatus.matches</code>
+	 * @return <code>true</code> if the given status should be displayed, and
+	 *         <code>false</code> otherwise
+	 * @see org.eclipse.core.runtime.IStatus#matches(int)
+	 */
+	protected static boolean shouldDisplay(IStatus status, int mask) {
+		IStatus[] children = status.getChildren();
+		if (children == null || children.length == 0) {
+			return status.matches(mask);
+		}
+		for (int i = 0; i < children.length; i++) {
+			if (children[i].matches(mask))
+				return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Toggles the unfolding of the details area. This is triggered by the user
+	 * pressing the details button.
+	 */
+	private void toggleDetailsArea() {
+		Point windowSize = getShell().getSize();
+		Point oldSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
+		if (listCreated) {
+			list.dispose();
+			listCreated = false;
+			detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL);
+		} else {
+			list = createDropDownList((Composite) getContents());
+			detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL);
+		}
+		Point newSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT);
+		getShell()
+				.setSize(
+						new Point(windowSize.x, windowSize.y
+								+ (newSize.y - oldSize.y)));
+	}
+
+	/**
+	 * Put the details of the status of the error onto the stream.
+	 * 
+	 * @param buildingStatus
+	 * @param buffer
+	 * @param nesting
+	 */
+	private void populateCopyBuffer(IStatus buildingStatus,
+			StringBuffer buffer, int nesting) {
+		if (!buildingStatus.matches(displayMask)) {
+			return;
+		}
+		for (int i = 0; i < nesting; i++) {
+			buffer.append(NESTING_INDENT); 
+		}
+		buffer.append(buildingStatus.getMessage());
+		buffer.append("\n"); //$NON-NLS-1$
+
+		// Look for a nested core exception
+		Throwable t = buildingStatus.getException();
+		if (t instanceof CoreException) {
+			CoreException ce = (CoreException) t;
+			populateCopyBuffer(ce.getStatus(), buffer, nesting + 1);
+		}
+
+		IStatus[] children = buildingStatus.getChildren();
+		for (int i = 0; i < children.length; i++) {
+			populateCopyBuffer(children[i], buffer, nesting + 1);
+		}
+	}
+
+	/**
+	 * Copy the contents of the statuses to the clipboard.
+	 */
+	private void copyToClipboard() {
+		if (clipboard != null)
+			clipboard.dispose();
+		StringBuffer statusBuffer = new StringBuffer();
+		populateCopyBuffer(status, statusBuffer, 0);
+		clipboard = new Clipboard(list.getDisplay());
+		clipboard.setContents(new Object[] { statusBuffer.toString() },
+				new Transfer[] { TextTransfer.getInstance() });
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.eclipse.jface.window.Window#close()
+	 */
+	public boolean close() {
+		if (clipboard != null)
+			clipboard.dispose();
+		return super.close();
+	}
+
+	/**
+	 * Show the details portion of the dialog if it is not already visible. This
+	 * method will only work when it is invoked after the control of the dialog
+	 * has been set. In other words, after the <code>createContents</code>
+	 * method has been invoked and has returned the control for the content area
+	 * of the dialog. Invoking the method before the content area has been set
+	 * or after the dialog has been disposed will have no effect.
+	 * 
+	 * @since 3.1
+	 */
+	protected final void showDetailsArea() {
+		if (!listCreated) {
+			Control control = getContents();
+			if (control != null && !control.isDisposed())
+				toggleDetailsArea();
+		}
+	}
+
+	/**
+	 * Return whether the Details button should be included. This method is
+	 * invoked once when the dialog is built. By default, the Details button is
+	 * only included if the status used when creating the dialog was a
+	 * multi-status or if the status contains an exception. Subclasses may
+	 * override.
+	 * 
+	 * @return whether the Details button should be included
+	 * @since 3.1
+	 */
+	protected boolean shouldShowDetailsButton() {
+		return status.isMultiStatus() || status.getException() != null;
+	}
+
+	/**
+	 * Set the status displayed by this error dialog to the given status. This
+	 * only affects the status displayed by the Details list. The message, image
+	 * and title should be updated by the subclass, if desired.
+	 * 
+	 * @param status
+	 *            the status to be displayed in the details list
+	 * @since 3.1
+	 */
+	protected final void setStatus(IStatus status) {
+		if (this.status != status) {
+			this.status = status;
+		}
+		shouldIncludeTopLevelErrorInDetails = true;
+		if (listCreated) {
+			repopulateList();
+		}
+	}
+
+	/**
+	 * Repopulate the supplied list widget.
+	 */
+	private void repopulateList() {
+		if (list != null && !list.isDisposed()) {
+			list.removeAll();
+			populateList(list);
+		}
+	}
+
+}
\ No newline at end of file
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MenuUtil.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MenuUtil.java
new file mode 100644
index 0000000..658a661
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MenuUtil.java
@@ -0,0 +1,47 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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 implementation
+//------------------------------------------------------------------------------
+package org.eclipse.epf.common.ui.util;
+
+import org.eclipse.swt.widgets.MenuItem;
+
+/**
+ * A helper class for retrieving Eclipse menus.
+ * 
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class MenuUtil {
+
+	/**
+	 * Searches an array of menu items and returns the menu item that matches
+	 * the given menu text.
+	 * 
+	 * @param menuItems
+	 *            An array of menu items.
+	 * @param text
+	 *            The text to look for.
+	 * @return The menu item if found, <code>null</code> otherwise.
+	 */
+	public static MenuItem getMenuItem(MenuItem[] menuItems, String text) {
+		if (menuItems == null || text == null || text.length() == 0) {
+			return null;
+		}
+
+		for (int i = 0; i < menuItems.length; i++) {
+			if (menuItems[i].getText().startsWith(text)) {
+				return menuItems[i];
+			}
+		}
+
+		return null;
+	}
+
+}
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgBox.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgBox.java
new file mode 100644
index 0000000..2c79eb3
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgBox.java
@@ -0,0 +1,123 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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 implementation
+//------------------------------------------------------------------------------
+package org.eclipse.epf.common.ui.util;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Helper class to display a message box.
+ * 
+ * @author Phong Nguyen Le
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public final class MsgBox {
+	/**
+	 * Use this method to show error message if you don't want long path to be
+	 * cut off.
+	 * 
+	 * @param msg
+	 */
+	public static final void nativeShowError(Shell shell, String msg) {
+		if (shell == null) {
+			shell = getDefaultShell();
+			if (shell == null) {
+				return;
+			}
+		}
+		MessageBox msgBox = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
+		msgBox.setMessage(msg);
+		msgBox.setText(shell.getText());
+		msgBox.open();
+	}
+
+	public static final void showError(String msg) {
+		showError(getDefaultShell(), msg);
+	}
+
+	public static final void showError(Shell shell, String msg) {
+		WrappedMessageDialog.openError(shell, shell == null ? null : shell
+				.getText(), msg);
+	}
+
+	public static final void showWarning(String msg) {
+		showWarning(getDefaultShell(), msg);
+	}
+
+	public static final void showWarning(Shell shell, String msg) {
+		WrappedMessageDialog.openWarning(shell, shell == null ? null : shell
+				.getText(), msg);
+	}
+
+	public static final Shell getDefaultShell() {
+		try {
+			Display d = Display.getCurrent();
+			if (d == null) {
+				d = Display.getDefault();
+			}
+
+			Shell s = null;
+			if (d != null) {
+				s = d.getActiveShell();
+			}
+
+			return s;
+		} catch (RuntimeException e) {
+			return null;
+		}
+	}
+
+	public static final Display getDisplay() {
+		try {
+			Display d = Display.getCurrent();
+			if (d == null) {
+				d = Display.getDefault();
+			}
+
+			return d;
+		} catch (RuntimeException e) {
+			return null;
+		}
+	}
+
+	public static final int prompt(String msg) {
+		return prompt(getDefaultShell(), msg);
+	}
+
+	public static final int prompt(Shell shell, String msg) {
+		return prompt(shell, null, msg, SWT.YES | SWT.NO | SWT.CANCEL);
+	}
+
+	public static final int prompt(String msg, int buttons) {
+		return prompt(getDefaultShell(), null, msg, buttons);
+	}
+
+	public static final int prompt(String title, String msg, int buttons) {
+		return prompt(getDefaultShell(), title, msg, buttons);
+	}
+
+	public static final int prompt(Shell shell, String msg, int buttons) {
+		return prompt(shell, null, msg, buttons);
+	}
+
+	public static final int prompt(Shell shell, String title, String msg,
+			int buttons) {
+		MessageBox msgBox = new MessageBox(shell, buttons | SWT.ICON_QUESTION);
+		msgBox.setText(title != null && title.length() > 0 ? title : shell
+				.getText());
+		msgBox.setMessage(msg);
+		return msgBox.open();
+	}
+
+}
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgDialog.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgDialog.java
new file mode 100644
index 0000000..ab700b3
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/MsgDialog.java
@@ -0,0 +1,628 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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 implementation
+//------------------------------------------------------------------------------
+package org.eclipse.epf.common.ui.util;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.epf.common.AbstractActivator;
+import org.eclipse.epf.common.serviceability.Logger;
+import org.eclipse.epf.common.ui.AbstractPlugin;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * A message dialog used for displaying error, warning, confirmation or
+ * informational messages.
+ * 
+ * @author Kelvin Low
+ * @author Jinhua Xi
+ * @since 1.0
+ */
+public class MsgDialog {
+
+	// The plug-in instance.
+	private Plugin plugin;
+
+	// The plug-in ID.
+	private String pluginId;
+
+	// The plug-in logger.
+	private Logger logger;
+	
+	private Shell shell;
+
+	/**
+	 * Create a new instance given the plug-in instance.
+	 * 
+	 * @param plugin
+	 *            The plugin instance.
+	 */
+	public MsgDialog(AbstractPlugin plugin) {
+		this.plugin = plugin;
+		this.shell = plugin.getWorkbench().getDisplay().getActiveShell();
+		this.pluginId = plugin.getId();
+		this.logger = plugin.getLogger();
+	}
+
+	public MsgDialog(AbstractActivator plugin, Shell shell) {
+		this.plugin = plugin;
+		this.shell = shell;
+		this.pluginId = plugin.getId();
+		this.logger = plugin.getLogger();
+	}
+	
+	/**
+	 * Displays the given error message in an error dialog without the error
+	 * reason and Details button.
+	 * <p>
+	 * Note: The error message will be written to the log file.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param msg
+	 *            The error message.
+	 */
+	public void displayError(String title, String msg) {
+		display(IStatus.ERROR, title, msg, null, null, null);
+	}
+
+	/**
+	 * Displays the given error message in an error dialog without the error
+	 * reason and Details button.
+	 * <p>
+	 * Note: The error message and the exception stack trace will be written to
+	 * the log file.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param msg
+	 *            The error message.
+	 * @param ex
+	 *            The exception associated with the error.
+	 */
+	public void displayError(String title, String msg, Throwable ex) {
+		display(IStatus.ERROR, title, msg, null, null, ex);
+	}
+
+	/**
+	 * Displays the given error message in an error dialog without the Details
+	 * button.
+	 * <p>
+	 * Note: The error message will be written to the log file.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param msg
+	 *            The error message.
+	 * @param reason
+	 *            The reason for the error.
+	 */
+	public void displayError(String title, String msg, String reason) {
+		display(IStatus.ERROR, title, msg, reason, null, null);
+	}
+
+	/**
+	 * Displays the given error message in an error dialog without the Details
+	 * button.
+	 * <p>
+	 * Note: The error message and the exception stack trace will be written to
+	 * the log file.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param msg
+	 *            The error message.
+	 * @param reason
+	 *            The reason for the error.
+	 * @param ex
+	 *            The exception associated with the error.
+	 */
+	public void displayError(String title, String msg, String reason,
+			Throwable ex) {
+		display(IStatus.ERROR, title, msg, reason, null, ex);
+	}
+
+	/**
+	 * Displays the given error message in an error dialog. The Details button
+	 * will be displayed if the <code>details</code> parameter it not null or
+	 * empty.
+	 * <p>
+	 * Note: The error message will be written to the log file.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param msg
+	 *            The error message.
+	 * @param reason
+	 *            The reason for the error.
+	 * @param details
+	 *            The error details.
+	 */
+	public void displayError(String title, String msg, String reason,
+			String details) {
+		display(IStatus.ERROR, title, msg, reason, details, null);
+	}
+
+	/**
+	 * Displays the given error message in an error dialog. The Details button
+	 * will be displayed if the <code>details</code> parameter it not null or
+	 * empty.
+	 * <p>
+	 * Note: The error message and the exception stack trace will be written to
+	 * the log file.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param msg
+	 *            The error message.
+	 * @param reason
+	 *            The reason for the error.
+	 * @param details
+	 *            The error details.
+	 * @param ex
+	 *            The exception associated with the error.
+	 */
+	public void displayError(String title, String msg, String reason,
+			String details, Throwable ex) {
+		display(IStatus.ERROR, title, msg, reason, details, ex);
+	}
+
+	/**
+	 * Displays the given error status in an error dialog.
+	 * <p>
+	 * Note: The error message and the exception stack trace will be written to
+	 * the log file.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param status
+	 *            The error status.
+	 */
+	public int displayError(String title, IStatus status) {
+		return display(title, null, status);
+	}
+
+	/**
+	 * Displays the given error status in an error dialog.
+	 * <p>
+	 * Note: The error message and the exception stack trace will be written to
+	 * the log file.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param msg
+	 *            The error message.
+	 * @param status
+	 *            The error status.
+	 */
+	public int displayError(String title, String msg, IStatus status) {
+		return display(title, msg, status);
+	}
+
+	/**
+	 * Displays the given warning message in a warning dialog without the
+	 * warning reason and Details button.
+	 * <p>
+	 * Note: The waning message will be written to the log file.
+	 * 
+	 * @param title
+	 *            The title for the warning dialog.
+	 * @param msg
+	 *            The warning message.
+	 */
+	public void displayWarning(String title, String msg) {
+		display(IStatus.WARNING, title, msg, null, null, null);
+	}
+	
+	/**
+	 * Displays the given warning message in a warning dialog without the
+	 * warning reason and Details button.
+	 * <p>
+	 * Note: The warning message and the exception stack trace will be written
+	 * to the log file.
+	 * 
+	 * @param title
+	 *            The title for the warning dialog.
+	 * @param msg
+	 *            The warning message.
+	 * @param ex
+	 *            The exception associated with the warning.
+	 */
+	public void displayWarning(String title, String msg, Throwable ex) {
+		display(IStatus.WARNING, title, msg, null, null, ex);
+	}
+
+	/**
+	 * Displays the given warning message in a warning dialog without the
+	 * warning reason and Details button.
+	 * <p>
+	 * Note: The waning message will be written to the log file.
+	 * 
+	 * @param title
+	 *            The title for the warning dialog.
+	 * @param msg
+	 *            The warning message.
+	 * @param reason
+	 *            The reason for the warning.
+	 */
+	public void displayWarning(String title, String msg, String reason) {
+		display(IStatus.WARNING, title, msg, reason, null, null);
+	}
+
+	/**
+	 * Displays the given warning message in a warning dialog without the
+	 * warning reason and Details button.
+	 * <p>
+	 * Note: The warning message and the exception stack trace will be written
+	 * to the log file.
+	 * 
+	 * @param title
+	 *            The title for the warning dialog.
+	 * @param msg
+	 *            The warning message.
+	 * @param reason
+	 *            The reason for the warning.
+	 * @param ex
+	 *            The exception associated with the warning.
+	 */
+	public void displayWarning(String title, String msg, String reason,
+			Throwable ex) {
+		display(IStatus.WARNING, title, msg, reason, null, ex);
+	}
+
+	/**
+	 * Displays the given warning message in a warning dialog. The Details
+	 * button will be displayed if the <code>details</code> parameter it not
+	 * null or empty.
+	 * <p>
+	 * Note: The waning message will be written to the log file.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param msg
+	 *            The warning message.
+	 * @param reason
+	 *            The reason for the warning.
+	 * @param details
+	 *            The warning details.
+	 */
+	public void displayWarning(String title, String msg, String reason,
+			String details) {
+		display(IStatus.WARNING, title, msg, reason, details, null);
+	}
+
+	/**
+	 * Displays the given warning message in a warning dialog. The Details
+	 * button will be displayed if the <code>details</code> parameter it not
+	 * null or empty.
+	 * <p>
+	 * Note: The warning message and the exception stack trace will be written
+	 * to the log file.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param msg
+	 *            The warning message.
+	 * @param reason
+	 *            The reason for the warning.
+	 * @param details
+	 *            The warning details.
+	 * @param ex
+	 *            The exception associated with the warning.
+	 */
+	public void displayWarning(String title, String msg, String reason,
+			String details, Throwable ex) {
+		display(IStatus.WARNING, title, msg, reason, details, ex);
+	}
+
+	/**
+	 * Displays the given warning status in an error dialog.
+	 * <p>
+	 * Note: The warning message and the exception stack trace will be written
+	 * to the log file.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param status
+	 *            The error status.
+	 */
+	public void displayWarning(String title, IStatus status) {
+		display(title, null, status);
+	}
+
+	/**
+	 * Displays the given warning status in an error dialog.
+	 * <p>
+	 * Note: The warning message and the exception stack trace will be written
+	 * to the log file.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param msg
+	 *            The error message.
+	 * @param status
+	 *            The error status.
+	 */
+	public void displayWarning(String title, String msg, IStatus status) {
+		display(title, msg, status);
+	}
+
+	/**
+	 * Displays the given error or warning message in an error or warning
+	 * dialog. The Details button will be displayed if the <code>details</code>
+	 * parameter it not null or empty.
+	 * 
+	 * @param severity
+	 *            The severity, either IStatus.ERROR or IStatus.WARNING.
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param msg
+	 *            The error message.
+	 * @param reason
+	 *            The reason for the error.
+	 * @param details
+	 *            The error details.
+	 * @param ex
+	 *            The exception associated with the error.
+	 */
+	public synchronized void display(int severity, String title, String msg,
+			String reason, String details, Throwable ex) {
+		if (msg == null && ex != null) {
+			msg = ex.getMessage();
+		}
+
+		if (msg == null) {
+			msg = ""; //$NON-NLS-1$
+		}
+
+		if (severity == IStatus.ERROR || severity == IStatus.WARNING) {
+			logger.logMsg(severity, msg, ex);
+		} else {
+			throw new IllegalArgumentException(
+					"severity argument must be IStatus.ERROR or IStatus.WARNING"); //$NON-NLS-1$
+		}
+
+		Image oldImage = org.eclipse.jface.dialogs.ErrorDialog
+				.getDefaultImage();
+		Image shellImage = getShellImage();
+		if (shellImage != null) {
+			ErrorDialog.setDefaultImage(shellImage);
+		}
+
+		//Shell shell = plugin.getWorkbench().getDisplay().getActiveShell();
+
+		if (details != null && details.length() > 0) {
+			MultiStatus mStatus = new MultiStatus(pluginId, IStatus.OK, reason,
+					ex);
+			Status status = new Status(severity, pluginId, IStatus.OK, details,
+					ex);
+			mStatus.add(status);
+			org.eclipse.jface.dialogs.ErrorDialog.openError(shell, title, msg,
+					mStatus);
+		} else if (reason != null && reason.length() > 0) {
+			Status status = new Status(severity, pluginId, IStatus.OK, reason,
+					ex);
+			org.eclipse.jface.dialogs.ErrorDialog.openError(shell, title, msg,
+					status);
+		} else {
+			if (severity == IStatus.ERROR) {
+				WrappedMessageDialog.openError(shell, title, msg);
+			} else if (severity == IStatus.WARNING) {
+				WrappedMessageDialog.openWarning(shell, title, msg);
+			}
+		}
+
+		if (shellImage != null) {
+			ErrorDialog.setDefaultImage(oldImage);
+		}
+	}
+
+	/**
+	 * Displays the given error or warning message in an error or warning
+	 * dialog. The Details button will be displayed if the <code>details</code>
+	 * parameter it not null or empty.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param status
+	 *            The error status.
+	 */
+	public synchronized int display(String title, IStatus status) {
+		return display(title, null, status);
+	}
+
+	/**
+	 * Displays the given error or warning message in an error or warning
+	 * dialog. The Details button will be displayed if the <code>details</code>
+	 * parameter it not null or empty.
+	 * 
+	 * @param title
+	 *            The title for the error dialog.
+	 * @param msg
+	 *            The error message.
+	 * @param status
+	 *            The error status.
+	 */
+	public synchronized int display(String title, String msg, IStatus status) {
+		if (status == null) {
+			throw new IllegalArgumentException("status argument cannot be null"); //$NON-NLS-1$
+		}
+
+		if (msg == null) {
+			msg = status.getMessage();
+		}
+		if (msg == null) {
+			msg = ""; //$NON-NLS-1$
+		}
+
+		int severity = status.getSeverity();
+		if (severity == IStatus.ERROR || severity == IStatus.WARNING) {
+			logger.logMsg(severity, msg, status.getException());
+		}
+
+		Image oldImage = org.eclipse.jface.dialogs.ErrorDialog
+				.getDefaultImage();
+		Image shellImage = getShellImage();
+		if (shellImage != null) {
+			ErrorDialog.setDefaultImage(shellImage);
+		}
+
+		//Shell shell = plugin.getWorkbench().getDisplay().getActiveShell();
+
+		int rc = org.eclipse.jface.dialogs.ErrorDialog.openError(shell, title,
+				msg, status);
+
+		if (shellImage != null) {
+			ErrorDialog.setDefaultImage(oldImage);
+		}
+
+		return rc;
+	}
+
+	/**
+	 * Displays the given message in a informational dialog with an "OK" button.
+	 * 
+	 * @param title
+	 *            The title for the information dialog.
+	 * @param msg
+	 *            The message to display.
+	 */
+	public void displayInfo(String title, String msg) {
+		if (msg == null) {
+			msg = ""; //$NON-NLS-1$
+		}
+
+		Image oldImage = WrappedMessageDialog.getDefaultImage();
+		Image shellImage = getShellImage();
+		if (shellImage != null) {
+			WrappedMessageDialog.setDefaultImage(shellImage);
+		}
+
+		//Shell shell = plugin.getWorkbench().getDisplay().getActiveShell();
+		WrappedMessageDialog.openInformation(shell, title, msg);
+
+		if (shellImage != null) {
+			WrappedMessageDialog.setDefaultImage(oldImage);
+		}
+	}
+
+	/**
+	 * Displays the given message in a question dialog with a "Yes" and "No"
+	 * button.
+	 * 
+	 * @param title
+	 *            The title for the information dialog.
+	 * @param msg
+	 *            The message to display.
+	 */
+	public boolean displayPrompt(String title, String msg) {
+		if (msg == null) {
+			msg = ""; //$NON-NLS-1$
+		}
+
+		Image oldImage = WrappedMessageDialog.getDefaultImage();
+		Image shellImage = getShellImage();
+		if (shellImage != null) {
+			WrappedMessageDialog.setDefaultImage(shellImage);
+		}
+
+		//Shell shell = plugin.getWorkbench().getDisplay().getActiveShell();
+		boolean result = WrappedMessageDialog.openQuestion(shell, title, msg);
+
+		if (shellImage != null) {
+			WrappedMessageDialog.setDefaultImage(oldImage);
+		}
+
+		return result;
+	}
+
+	/**
+	 * Displays the given message in a confirmation dialog with a "Yes" and
+	 * "Cancel" button.
+	 * 
+	 * @param title
+	 *            The title for the information dialog.
+	 * @param msg
+	 *            The message to display.
+	 */
+	public boolean displayConfirmation(String title, String msg) {
+		if (msg == null) {
+			msg = ""; //$NON-NLS-1$
+		}
+
+		Image oldImage = WrappedMessageDialog.getDefaultImage();
+		Image shellImage = getShellImage();
+		if (shellImage != null) {
+			WrappedMessageDialog.setDefaultImage(shellImage);
+		}
+
+		//Shell shell = plugin.getWorkbench().getDisplay().getActiveShell();
+		boolean result = WrappedMessageDialog.openConfirm(shell, title, msg);
+
+		if (shellImage != null) {
+			WrappedMessageDialog.setDefaultImage(oldImage);
+		}
+
+		return result;
+	}
+
+	public int displayConfirmation(String title, String msg, IStatus status) {
+		if (status == null) {
+			throw new IllegalArgumentException("status argument cannot be null"); //$NON-NLS-1$
+		}
+
+		if (msg == null) {
+			msg = status.getMessage();
+		}
+		if (msg == null) {
+			msg = ""; //$NON-NLS-1$
+		}
+
+		Image shellImage = getShellImage();
+		if (shellImage != null) {
+			ErrorDialogNoReason.setDefaultImage(shellImage);
+		}
+
+		//Shell shell = plugin.getWorkbench().getDisplay().getActiveShell();
+
+		int rc = ErrorDialogNoReason.openError(shell, title, msg, status);
+
+		return rc;
+
+	}
+
+	/**
+	 * Returns the image for the current shell.
+	 * 
+	 * @return The current shell image.
+	 */
+	private Image getShellImage() {
+		IWorkbench workbench = PlatformUI.getWorkbench();
+		if (workbench != null) {
+			IWorkbenchWindow workbenchWindow = workbench
+					.getActiveWorkbenchWindow();
+			if (workbenchWindow != null) {
+				Shell shell = workbenchWindow.getShell();
+				if (shell != null) {
+					return shell.getImage();
+				}
+			}
+		}
+		return null;
+	}
+
+}
\ No newline at end of file
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PerspectiveUtil.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PerspectiveUtil.java
new file mode 100644
index 0000000..c81736f
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PerspectiveUtil.java
@@ -0,0 +1,122 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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 implementation
+//------------------------------------------------------------------------------
+package org.eclipse.epf.common.ui.util;
+
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.IPerspectiveRegistry;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.WorkbenchException;
+
+/**
+ * Utility class for accessing perspectives.
+ * 
+ * @author Kelvin Low
+ * @since 1.0
+ */
+public class PerspectiveUtil {
+
+	/**
+	 * Private constructor to prevent this class from being instantiated. All
+	 * methods in this class should be static.
+	 */
+	private PerspectiveUtil() {
+	}
+
+	/**
+	 * Returns the ID of the active perspective.
+	 * 
+	 * @return The active perspective ID.
+	 */
+	public static String getActivePerspectiveId() {
+		IWorkbenchPage activePage = PlatformUI.getWorkbench()
+				.getActiveWorkbenchWindow().getActivePage();
+		if (activePage != null) {
+			IPerspectiveDescriptor activePerspective = activePage
+					.getPerspective();
+			return activePerspective.getId();
+		}
+		return null;
+	}
+
+	/**
+	 * Opens a perspective.
+	 * 
+	 * @param perspectiveId
+	 *            The perspective ID.
+	 * @return The previously active perspective.
+	 */
+	public static IPerspectiveDescriptor openPerspective(String perspectiveId) {
+		IWorkbenchPage activePage = PlatformUI.getWorkbench()
+				.getActiveWorkbenchWindow().getActivePage();
+		if (activePage != null) {
+			IPerspectiveRegistry registry = PlatformUI.getWorkbench()
+					.getPerspectiveRegistry();
+			IPerspectiveDescriptor oldPerspective = activePage.getPerspective();
+			if (!oldPerspective.getId().equals(perspectiveId)) {
+				IPerspectiveDescriptor perspective = registry
+						.findPerspectiveWithId(perspectiveId);
+				activePage.setPerspective(perspective);
+			}
+			return oldPerspective;
+		} else {
+			IWorkbenchWindow activeWindow = PlatformUI.getWorkbench()
+					.getActiveWorkbenchWindow();
+			try {
+				PlatformUI.getWorkbench().showPerspective(
+						perspectiveId, activeWindow);
+			} catch (WorkbenchException e) {
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Returns true if the given perspective is already active.
+	 * 
+	 * @param perspectiveId
+	 *            The perspective ID.
+	 * @return
+	 */
+	public static boolean isActivePerspective(String perspectiveId) {
+		String activePerspectiveId = PerspectiveUtil.getActivePerspectiveId();
+		if (perspectiveId == null || activePerspectiveId == null) {
+			return false;
+		}
+		return activePerspectiveId.equalsIgnoreCase(perspectiveId);
+	}
+
+	/**
+	 * Returns the view part with the given view ID.
+	 * 
+	 * @param viewId
+	 *            The view ID.
+	 * @return The view part.
+	 */
+	public static IViewPart getView(String viewId) {
+		try {
+			IWorkbenchPage activePage = PlatformUI.getWorkbench()
+					.getActiveWorkbenchWindow().getActivePage();
+			if (activePage != null) {
+				IViewPart view = activePage.findView(viewId);
+				if (view == null) {
+					view = activePage.showView(viewId);
+				}
+				return view;
+			}
+		} catch (Exception e) {
+		}
+		return null;
+	}
+
+}
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PreferenceUtil.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PreferenceUtil.java
new file mode 100644
index 0000000..aa80bc5
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/PreferenceUtil.java
@@ -0,0 +1,166 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2007 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 implementation
+//------------------------------------------------------------------------------
+package org.eclipse.epf.common.ui.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+
+import com.ibm.icu.util.StringTokenizer;
+
+/**
+ * Utility class for accessing preferences.
+ * 
+ * @author Kelvin Low
+ * @since 1.2
+ */
+public class PreferenceUtil {
+
+	// The multi-string preference delimiter.
+	private static final String PREFERENCE_DELIMITER = ";"; //$NON-NLS-1$
+
+	/**
+	 * Gets a list containing string values associated with a named preference.
+	 * 
+	 * @param prefStore
+	 *            a preference store
+	 * @param name
+	 *            the preference name
+	 * @return a list of string values
+	 */
+	public static List<String> getList(IPreferenceStore prefStore, String name) {
+		List<String> values = new ArrayList<String>();
+		if (prefStore != null && name != null) {
+			String value = prefStore.getString(name);
+			StringTokenizer tokenizer = new StringTokenizer(value,
+					PREFERENCE_DELIMITER);
+			int tokenCount = tokenizer.countTokens();
+			for (int i = 0; i < tokenCount; i++) {
+				values.add(tokenizer.nextToken());
+			}
+		}
+		return values;
+	}
+
+	/**
+	 * Gets the string values associated with a named preference.
+	 * 
+	 * @param prefStore
+	 *            a preference store
+	 * @param name
+	 *            the preference name
+	 * @return a list of string preference values
+	 */
+	public static String[] getStringValues(IPreferenceStore prefStore,
+			String name) {
+		List<String> list = getList(prefStore, name);
+		String[] values = new String[list.size()];
+		list.toArray(values);
+		return values;
+	}
+
+	/**
+	 * Saves a list containing string values associated with a named preference.
+	 * 
+	 * @param prefStore
+	 *            a preference store
+	 * @param name
+	 *            the preference name
+	 * @param values
+	 *            a list of string values
+	 */
+	public static void setList(IPreferenceStore prefStore, String name,
+			List values) {
+		if (prefStore != null && name != null && values != null) {
+			StringBuffer buffer = new StringBuffer();
+			for (Iterator it = values.iterator(); it.hasNext();) {
+				String value = (String) it.next();
+				buffer.append(value);
+				buffer.append(PREFERENCE_DELIMITER);
+			}
+			prefStore.setValue(name, buffer.toString());
+		}
+	}
+
+	/**
+	 * Adds a string value to a list containing string values associated with a
+	 * named preference.
+	 * 
+	 * @param prefStore
+	 *            a preference store
+	 * @param name
+	 *            the preference name
+	 * @param value
+	 *            a string value
+	 * @param defaultValue
+	 *            a default string value that will be added to the end of the
+	 *            list
+	 */
+	public static void addToList(IPreferenceStore prefStore, String name,
+			String value, String defaultValue) {
+		if (prefStore != null && name != null && value != null) {
+			List<String> list = getList(prefStore, name);
+			list.remove(value);
+			list.add(0, value);
+			int preferenceHistorySize = CommonPreferences
+					.getPreferenceHistorySize();
+			if (list.size() > preferenceHistorySize) {
+				list = list.subList(0, 10);
+			}
+			if (list.size() == preferenceHistorySize && defaultValue != null
+					&& defaultValue.length() > 0) {
+				list.set(9, defaultValue);
+			}
+			setList(prefStore, name, list);
+		}
+	}
+
+	/**
+	 * Adds a string value to a list containing string values associated with a
+	 * named preference.
+	 * 
+	 * @param prefStore
+	 *            a preference store
+	 * @param name
+	 *            the preference name
+	 * @param value
+	 *            a string value
+	 */
+	public static void addToList(IPreferenceStore prefStore, String name,
+			String value) {
+		addToList(prefStore, name, value, null);
+	}
+
+	/**
+	 * Saves an array of string values associated with a named preference.
+	 * 
+	 * @param prefStore
+	 *            a preference store
+	 * @param name
+	 *            the preference name
+	 * @param values
+	 *            an array of string values
+	 */
+	public static void setStringValues(IPreferenceStore prefStore, String name,
+			String[] values) {
+		if (prefStore != null && name != null && values != null) {
+			StringBuffer buffer = new StringBuffer();
+			for (int i = 0; i < values.length; i++) {
+				buffer.append(values[i]);
+				buffer.append(PREFERENCE_DELIMITER);
+			}
+			prefStore.setValue(name, buffer.toString());
+		}
+	}
+
+}
diff --git a/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/WrappedMessageDialog.java b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/WrappedMessageDialog.java
new file mode 100644
index 0000000..be5cf0f
--- /dev/null
+++ b/2.0/plugins/org.eclipse.epf.common.ui/src/org/eclipse/epf/common/ui/util/WrappedMessageDialog.java
@@ -0,0 +1,150 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2005, 2006 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 implementation
+//------------------------------------------------------------------------------
+package org.eclipse.epf.common.ui.util;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Displays a message dialog that displays wrapped text.
+ * 
+ * @author Bingxue Xu
+ * @since 1.0
+ */
+public class WrappedMessageDialog extends MessageDialog {
+
+	public WrappedMessageDialog(Shell parentShell, String dialogTitle,
+			Image dialogTitleImage, String dialogMessage, int dialogImageType,
+			String[] dialogButtonLabels, int defaultIndex) {
+		super(parentShell, dialogTitle, dialogTitleImage, dialogMessage,
+				dialogImageType, dialogButtonLabels, defaultIndex);
+	}
+
+	protected Control createMessageArea(Composite composite) {
+
+		Control rComposite = super.createMessageArea(composite);
+
+		int minWidth = IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH;// + 300;
+		// TO-DO: need to revist the # of dialog display units and margin
+		// when in other languages
+		int charsPerLine = minWidth / 4 - 15;
+		GridData gd = (GridData) messageLabel.getLayoutData();
+		gd.minimumWidth = minWidth;
+		messageLabel.setText(addLineBreaks(message, charsPerLine));
+
+		return rComposite;
+	}
+
+	String addLineBreaks(String msg, int maxChars) {
+		// System.out.println("$$$ DEBUG: original message = " + msg);
+
+		if (msg == null)
+			return null;
+
+		StringBuffer strBuf = new StringBuffer();
+		int count = 0;
+		for (int i = 0; i < msg.length(); i++) {
+			strBuf.append(msg.charAt(i));
+			if (Character.isWhitespace(msg.charAt(i)))
+				count = 0;
+			else
+				count++;
+
+			if (count >= maxChars) {
+				if (!Character.isWhitespace(msg.charAt(i))) {
+					strBuf.append("\n"); //$NON-NLS-1$
+				}
+				count = 0;
+			}
+		}
+
+		// System.out.println("$$$ DEBUG: broken message = " +
+		// strBuf.toString());
+		return strBuf.toString();
+	}
+
+	public static boolean openConfirm(Shell parent, String title, String message) {
+		WrappedMessageDialog dialog = new WrappedMessageDialog(parent, title,
+				null, // accept
+				// the
+				// default
+				// window
+				// icon
+				message, QUESTION, new String[] { IDialogConstants.OK_LABEL,
+						IDialogConstants.CANCEL_LABEL }, 0); // OK is the
+		// default
+		return dialog.open() == 0;
+	}
+
+	public static void openError(Shell parent, String title, String message) {
+		WrappedMessageDialog dialog = new WrappedMessageDialog(parent, title,
+				null, // accept
+				// the
+				// default
+				// window
+				// icon
+				message, ERROR, new String[] { IDialogConstants.OK_LABEL }, 0); // ok
+		// is
+		// the
+		// default
+		dialog.open();
+		return;
+	}
+
+	public static void openInformation(Shell parent, String title,
+			String message) {
+		WrappedMessageDialog dialog = new WrappedMessageDialog(parent, title,
+				null, // accept
+				// the
+				// default
+				// window
+				// icon
+				message, INFORMATION,
+				new String[] { IDialogConstants.OK_LABEL }, 0);
+		// ok is the default
+		dialog.open();
+		return;
+	}
+
+	public static boolean openQuestion(Shell parent, String title,
+			String message) {
+		WrappedMessageDialog dialog = new WrappedMessageDialog(parent, title,
+				null, // accept
+				// the
+				// default
+				// window
+				// icon
+				message, QUESTION, new String[] { IDialogConstants.YES_LABEL,
+						IDialogConstants.NO_LABEL }, 0); // yes is the
+		// default
+		return dialog.open() == 0;
+	}
+
+	public static void openWarning(Shell parent, String title, String message) {
+		WrappedMessageDialog dialog = new WrappedMessageDialog(parent, title,
+				null, // accept
+				// the
+				// default
+				// window
+				// icon
+				message, WARNING, new String[] { IDialogConstants.OK_LABEL }, 0); // ok
+		// is
+		// the
+		// default
+		dialog.open();
+		return;
+	}
+}