From 2c6002fd955d7d41ae5cfdf2dc195b44ffe855ee Mon Sep 17 00:00:00 2001
From: Lukas Ladenberger <lukas.ladenberger@googlemail.com>
Date: Fri, 4 Jan 2013 12:49:42 +0100
Subject: [PATCH] implemented control panel for managing open simulations #2

---
 .../gef/editor/BMotionStudioLauncher.java     | 245 +++++++++++++++
 .../gef/editor/ISimulationListener.java       |  11 +
 .../AddVisualizationViewAction.java           |  73 +++++
 .../controlpanel/CloseSimulationAction.java   |  63 ++++
 .../gef/editor/controlpanel/ControlPanel.java | 295 ++++++++++++++++++
 .../controlpanel/SaveSimulationAction.java    | 118 +++++++
 .../gef/editor/util/PerspectiveUtil.java      | 149 +++++++++
 7 files changed, 954 insertions(+)
 create mode 100644 de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/BMotionStudioLauncher.java
 create mode 100644 de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/ISimulationListener.java
 create mode 100644 de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/AddVisualizationViewAction.java
 create mode 100644 de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/CloseSimulationAction.java
 create mode 100644 de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/ControlPanel.java
 create mode 100644 de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/SaveSimulationAction.java
 create mode 100644 de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/util/PerspectiveUtil.java

diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/BMotionStudioLauncher.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/BMotionStudioLauncher.java
new file mode 100644
index 00000000..7c0ec439
--- /dev/null
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/BMotionStudioLauncher.java
@@ -0,0 +1,245 @@
+package de.bmotionstudio.gef.editor;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.IExportedPreferences;
+import org.eclipse.core.runtime.preferences.IPreferenceFilter;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.core.runtime.preferences.PreferenceFilterEntry;
+import org.eclipse.ui.IEditorLauncher;
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.IPerspectiveRegistry;
+import org.eclipse.ui.IViewReference;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.PlatformUI;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.mapper.MapperWrapper;
+
+import de.bmotionstudio.gef.editor.model.Simulation;
+import de.bmotionstudio.gef.editor.model.Visualization;
+import de.bmotionstudio.gef.editor.model.VisualizationView;
+import de.bmotionstudio.gef.editor.util.PerspectiveUtil;
+
+
+public class BMotionStudioLauncher implements IEditorLauncher {
+
+	private Simulation simulation;
+
+	private IFile file;
+
+	@Override
+	public void open(IPath path) {
+
+		file = ResourcesPlugin.getWorkspace().getRoot()
+				.getFileForLocation(path);
+
+		if (BMotionEditorPlugin.getOpenSimulations()
+				.containsKey(file.getName()))
+			return;
+
+		InputStream inputStream = null;
+
+		try {
+
+			inputStream = file.getContents();
+
+			XStream xstream = new XStream() {
+				@Override
+				protected MapperWrapper wrapMapper(final MapperWrapper next) {
+					return new MapperWrapper(next) {
+						@Override
+						public boolean shouldSerializeMember(
+								@SuppressWarnings("rawtypes") final Class definedIn,
+								final String fieldName) {
+							if (definedIn == Object.class)
+								return false;
+							return super.shouldSerializeMember(definedIn,
+									fieldName);
+						}
+					};
+				}
+			};
+
+			BMotionEditorPlugin.setAliases(xstream);
+			Object obj = xstream.fromXML(inputStream);
+
+			IWorkbenchPage activePage = PlatformUI.getWorkbench()
+					.getActiveWorkbenchWindow().getActivePage();
+			IWorkbenchPartSite site = activePage.getActivePart().getSite();
+
+			importPerspective(file.getProject().getFile(
+					getPerspectiveFileName()));
+			openPerspective(site.getPage());
+
+			if (obj instanceof Visualization) {
+
+				simulation = new Simulation();
+
+				Visualization visualization = (Visualization) obj;
+				visualization.setProjectFile(file);
+
+				VisualizationView visualizationView = new VisualizationView(
+						"New Visualization View", visualization);
+
+				String secId = UUID.randomUUID().toString();
+
+				simulation.getVisualizationViews()
+						.put(secId, visualizationView);
+
+			} else if (obj instanceof Simulation) {
+				simulation = (Simulation) obj;
+			}
+
+			if (simulation != null) {
+
+				simulation.setProjectFile(file);
+
+				for (Map.Entry<String, VisualizationView> entry : simulation
+						.getVisualizationViews().entrySet()) {
+
+					String secId = entry.getKey();
+					VisualizationView visView = entry.getValue();
+					Visualization vis = visView.getVisualization();
+					vis.setProjectFile(file);
+					// String partName = visView.getPartName();
+					// IViewReference viewReference = site.getPage()
+					// .findViewReference(VisualizationViewPart.ID, secId);
+					// Check if view already exists
+					// if (viewReference != null) {
+					// } else {
+					// If not, create a new one
+					VisualizationViewPart visualizationViewPart = PerspectiveUtil
+							.createVisualizationViewPart(
+							secId, visView);
+					if (!visualizationViewPart.isInitialized())
+						visualizationViewPart.init(simulation, visView);
+					// }
+
+				}
+
+				// Close all unused visualization views
+				for (IViewReference viewReference : site.getPage()
+						.getViewReferences()) {
+					if (viewReference.getId().equals(VisualizationViewPart.ID)) {
+						if (!simulation.getVisualizationViews().containsKey(
+								viewReference.getSecondaryId()))
+							site.getPage().hideView(viewReference);
+					}
+				}
+
+				BMotionEditorPlugin.openSimulation(simulation);
+
+			}
+
+		} catch (CoreException e) {
+			e.printStackTrace();
+		} finally {
+			try {
+				if (inputStream != null)
+					inputStream.close();
+			} catch (IOException e) {
+				// TODO Auto-generated catch block
+				e.printStackTrace();
+			}
+		}
+
+	}
+
+	private IPerspectiveDescriptor openPerspective(IWorkbenchPage page) {
+
+		if (page == null)
+			return null;
+
+		// Try to get the corresponding perspective
+		IPerspectiveRegistry perspectiveRegistry = page.getWorkbenchWindow()
+				.getWorkbench().getPerspectiveRegistry();
+		String perspectiveId = PerspectiveUtil.getPerspectiveIdFromFile(file);
+		IPerspectiveDescriptor perspective = perspectiveRegistry
+				.findPerspectiveWithId(perspectiveId);
+
+		// Yes --> just switch to this perspective
+		if (perspective != null) {
+			PerspectiveUtil.switchPerspective(perspective);
+		} else {
+			// No --> create a new one
+			IPerspectiveDescriptor originalPerspectiveDescriptor = perspectiveRegistry
+					.findPerspectiveWithId(BMSPerspectiveFactory.ID);
+			PerspectiveUtil.switchPerspective(originalPerspectiveDescriptor);
+			perspective = perspectiveRegistry.clonePerspective(perspectiveId,
+					perspectiveId, originalPerspectiveDescriptor);
+			// save the perspective
+			page.savePerspectiveAs(perspective);
+		}
+
+		return perspective;
+
+	}
+
+	private void importPerspective(IFile perspectiveFile) {
+
+		FileInputStream fis = null;
+
+		try {
+
+			IPreferenceFilter[] transfers = null;
+			transfers = new IPreferenceFilter[1];
+
+			// Only import if a perspective file exists
+			if (perspectiveFile.exists()) {
+
+				File exportFile = new File(perspectiveFile.getLocationURI());
+				fis = new FileInputStream(exportFile);
+				IPreferencesService service = Platform.getPreferencesService();
+				// service.importPreferences(fis);
+				IExportedPreferences prefs = service.readPreferences(fis);
+				transfers[0] = new IPreferenceFilter() {
+					public String[] getScopes() {
+						return new String[] { InstanceScope.SCOPE };
+					}
+
+					public Map<String, PreferenceFilterEntry[]> getMapping(
+							String scope) {
+						Map<String, PreferenceFilterEntry[]> map = new HashMap<String, PreferenceFilterEntry[]>();
+						map.put("org.eclipse.ui.workbench",
+								new PreferenceFilterEntry[] { new PreferenceFilterEntry(
+										PerspectiveUtil
+												.getPerspectiveIdFromFile(file)
+												+ "_persp") });
+						return map;
+					}
+				};
+				service.applyPreferences(prefs, transfers);
+			}
+
+		} catch (FileNotFoundException e) {
+		} catch (CoreException e) {
+		} finally {
+			try {
+				if (fis != null)
+					fis.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+
+	}
+
+	private String getPerspectiveFileName() {
+		return file.getName().replace(".bmso", ".bmsop");
+	}
+
+}
diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/ISimulationListener.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/ISimulationListener.java
new file mode 100644
index 00000000..a73cca65
--- /dev/null
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/ISimulationListener.java
@@ -0,0 +1,11 @@
+package de.bmotionstudio.gef.editor;
+
+import de.bmotionstudio.gef.editor.model.Simulation;
+
+public interface ISimulationListener {
+
+	public void openSimulation(Simulation simulation);
+
+	public void closeSimulation(Simulation simulation);
+
+}
diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/AddVisualizationViewAction.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/AddVisualizationViewAction.java
new file mode 100644
index 00000000..84dfb0bb
--- /dev/null
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/AddVisualizationViewAction.java
@@ -0,0 +1,73 @@
+/** 
+ * (c) 2009 Lehrstuhl fuer Softwaretechnik und Programmiersprachen, 
+ * Heinrich Heine Universitaet Duesseldorf
+ * This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html) 
+ * */
+
+package de.bmotionstudio.gef.editor.controlpanel;
+
+import java.util.UUID;
+
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.ui.PartInitException;
+
+import de.bmotionstudio.gef.editor.BMotionEditorPlugin;
+import de.bmotionstudio.gef.editor.BMotionStudioImage;
+import de.bmotionstudio.gef.editor.model.Simulation;
+import de.bmotionstudio.gef.editor.model.Visualization;
+import de.bmotionstudio.gef.editor.model.VisualizationView;
+import de.bmotionstudio.gef.editor.util.PerspectiveUtil;
+
+public class AddVisualizationViewAction extends Action {
+
+	private TreeViewer viewer;
+
+	public AddVisualizationViewAction(TreeViewer viewer) {
+		this.viewer = viewer;
+		setText("Add View");
+		setImageDescriptor(BMotionStudioImage.getImageDescriptor(
+				"org.eclipse.ui", "$nl$/icons/full/etool16/new_wiz.gif"));
+	}
+
+	@Override
+	public void run() {
+
+		IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
+		Object firstElement = sel.getFirstElement();
+		if (firstElement instanceof Simulation) {
+
+			Simulation simulation = (Simulation) firstElement;
+
+			try {
+
+				String secId = UUID.randomUUID().toString();
+				// Create a new visualization
+				String version = Platform
+						.getBundle(BMotionEditorPlugin.PLUGIN_ID).getHeaders()
+						.get("Bundle-Version");
+				Visualization visualization = new Visualization(simulation
+						.getProjectFile().getName(), "EventB", version);
+
+				VisualizationView visualizationView = new VisualizationView(
+						"New Visualization View", visualization);
+				simulation.getVisualizationViews()
+						.put(secId, visualizationView);
+
+				PerspectiveUtil.createVisualizationViewPart(secId,
+						visualizationView);
+				
+				simulation.setDirty(true);
+				viewer.refresh();
+
+			} catch (PartInitException e1) {
+				e1.printStackTrace();
+			}
+
+		}
+
+	}
+
+}
diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/CloseSimulationAction.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/CloseSimulationAction.java
new file mode 100644
index 00000000..990c94a2
--- /dev/null
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/CloseSimulationAction.java
@@ -0,0 +1,63 @@
+/** 
+ * (c) 2009 Lehrstuhl fuer Softwaretechnik und Programmiersprachen, 
+ * Heinrich Heine Universitaet Duesseldorf
+ * This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html) 
+ * */
+
+package de.bmotionstudio.gef.editor.controlpanel;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.IPerspectiveRegistry;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PlatformUI;
+
+import de.bmotionstudio.gef.editor.BMotionEditorPlugin;
+import de.bmotionstudio.gef.editor.BMotionStudioImage;
+import de.bmotionstudio.gef.editor.model.Simulation;
+import de.bmotionstudio.gef.editor.util.PerspectiveUtil;
+
+public class CloseSimulationAction extends Action {
+
+	private TreeViewer viewer;
+
+	public CloseSimulationAction(TreeViewer viewer) {
+		this.viewer = viewer;
+		setText("Close Simulation");
+		setImageDescriptor(BMotionStudioImage.getImageDescriptor(
+				"org.eclipse.ui", "$nl$/icons/full/dlcl16/close_view.gif"));
+	}
+
+	@Override
+	public void run() {
+
+		IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
+		Object firstElement = sel.getFirstElement();
+		if (firstElement instanceof Simulation) {
+
+			IWorkbench workbench = PlatformUI.getWorkbench();
+			IWorkbenchPage page = workbench.getActiveWorkbenchWindow()
+					.getActivePage();
+
+			IPerspectiveRegistry perspectiveRegistry = workbench
+					.getPerspectiveRegistry();
+
+			Simulation simulation = (Simulation) firstElement;
+			String perspectiveId = PerspectiveUtil
+					.getPerspectiveIdFromFile(simulation.getProjectFile());
+			IPerspectiveDescriptor perspectiveDescriptor = perspectiveRegistry.findPerspectiveWithId(perspectiveId);
+			if(perspectiveDescriptor != null) {
+				PerspectiveUtil.closePerspective(page, perspectiveDescriptor);
+				PerspectiveUtil.deletePerspective(page, perspectiveDescriptor);
+			}
+			
+			BMotionEditorPlugin.closeSimulation(simulation);
+
+		}
+
+	}
+
+}
diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/ControlPanel.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/ControlPanel.java
new file mode 100644
index 00000000..c12f9a24
--- /dev/null
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/ControlPanel.java
@@ -0,0 +1,295 @@
+package de.bmotionstudio.gef.editor.controlpanel;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Collection;
+import java.util.EventObject;
+import java.util.Map;
+
+import org.eclipse.draw2d.ColorConstants;
+import org.eclipse.gef.commands.CommandStackListener;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableColorProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.TreeViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.ui.part.ViewPart;
+
+import de.bmotionstudio.gef.editor.BMotionEditorPlugin;
+import de.bmotionstudio.gef.editor.ISimulationListener;
+import de.bmotionstudio.gef.editor.model.Simulation;
+import de.bmotionstudio.gef.editor.model.VisualizationView;
+import de.bmotionstudio.gef.editor.util.PerspectiveUtil;
+
+public class ControlPanel extends ViewPart implements ISimulationListener,
+		CommandStackListener, PropertyChangeListener {
+
+	public static String ID = "de.bmotionstudio.gef.editor.ControlPanel";
+
+	private Composite container;
+
+	private TreeViewer treeViewer;
+
+	@Override
+	public void createPartControl(Composite parent) {
+
+		container = new Composite(parent, SWT.NONE);
+		GridLayout layout = new GridLayout(1, false);
+		layout.horizontalSpacing = 0;
+		layout.verticalSpacing = 0;
+		container.setLayout(layout);
+
+		Tree tree = new Tree(container, SWT.BORDER | SWT.H_SCROLL
+				| SWT.V_SCROLL | SWT.RESIZE);
+		tree.setHeaderVisible(true);
+		treeViewer = new TreeViewer(tree);
+
+		TreeViewerColumn column1 = new TreeViewerColumn(treeViewer, SWT.LEFT);
+		tree.setLinesVisible(true);
+		column1.getColumn().setAlignment(SWT.LEFT);
+		column1.getColumn().setText("Name");
+		column1.getColumn().setWidth(300);
+		// column1.setEditingSupport(new EditingSupport(treeViewer) {
+		//
+		// @Override
+		// protected void setValue(Object element, Object value) {
+		// if (element instanceof VisualizationView) {
+		// ((VisualizationView) element).setName(String.valueOf(value));
+		// treeViewer.update(element, null);
+		// }
+		// }
+		//
+		// @Override
+		// protected Object getValue(Object element) {
+		// if (element instanceof VisualizationView)
+		// return ((VisualizationView) element).getName();
+		// return null;
+		// }
+		//
+		// @Override
+		// protected CellEditor getCellEditor(Object element) {
+		// return new TextCellEditor(treeViewer.getTree());
+		// }
+		//
+		// @Override
+		// protected boolean canEdit(Object element) {
+		// if (element instanceof VisualizationView)
+		// return true;
+		// return false;
+		// }
+		//
+		// });
+
+		TreeViewerColumn column2 = new TreeViewerColumn(treeViewer, SWT.RIGHT);
+		column2.getColumn().setAlignment(SWT.LEFT);
+		column2.getColumn().setText("Dirty");
+		column2.getColumn().setWidth(40);
+
+		treeViewer.setContentProvider(new ITreeContentProvider() {
+
+			@Override
+			public void inputChanged(Viewer viewer, Object oldInput,
+					Object newInput) {
+			}
+
+			@Override
+			public void dispose() {
+			}
+
+			@Override
+			public boolean hasChildren(Object element) {
+				if (element instanceof Simulation)
+					return true;
+				return false;
+			}
+
+			@Override
+			public Object getParent(Object element) {
+				return null;
+			}
+
+			@Override
+			public Object[] getElements(Object inputElement) {
+				if (inputElement instanceof Collection<?>) {
+					Collection<?> l = (Collection<?>) inputElement;
+					return l.toArray(new Object[l.size()]);
+				}
+				return null;
+			}
+
+			@Override
+			public Object[] getChildren(Object parentElement) {
+				if (parentElement instanceof Simulation) {
+					Map<String, VisualizationView> visualizationViews = ((Simulation) parentElement)
+							.getVisualizationViews();
+					return visualizationViews.values().toArray(
+							new VisualizationView[visualizationViews.values()
+									.size()]);
+				}
+				return null;
+			}
+
+		});
+
+		treeViewer.setLabelProvider(new ControlLabelProvider());
+		treeViewer.addDoubleClickListener(new IDoubleClickListener() {
+			@Override
+			public void doubleClick(DoubleClickEvent event) {
+				IStructuredSelection sel = (IStructuredSelection) event
+						.getSelection();
+				Object firstElement = sel.getFirstElement();
+				if (firstElement instanceof Simulation) {
+					Simulation simulation = (Simulation) firstElement;
+					PerspectiveUtil.switchPerspective(PerspectiveUtil
+							.getPerspectiveIdFromFile(simulation
+									.getProjectFile()));
+				}
+
+			}
+		});
+
+		if (!BMotionEditorPlugin.getOpenSimulations().values().isEmpty()) {
+			treeViewer.setInput(BMotionEditorPlugin.getOpenSimulations()
+					.values());
+			treeViewer.expandAll();
+		}
+
+		MenuManager manager = new MenuManager();
+		manager.add(new CloseSimulationAction(treeViewer));
+		manager.add(new SaveSimulationAction(treeViewer));
+		manager.add(new Separator());
+		manager.add(new AddVisualizationViewAction(treeViewer));
+		treeViewer.getControl().setMenu(
+				manager.createContextMenu(treeViewer.getControl()));
+
+		GridData layoutData = new GridData(GridData.FILL_BOTH);
+		treeViewer.getControl().setLayoutData(layoutData);
+
+		BMotionEditorPlugin.openSimulationListeners.add(this);
+
+	}
+
+	@Override
+	public void setFocus() {
+	}
+
+	@Override
+	public void openSimulation(Simulation simulation) {
+		setInput(simulation);
+		simulation.addPropertyChangeListener(this);
+	}
+
+	@Override
+	public void closeSimulation(Simulation simulation) {
+		setInput(simulation);
+		simulation.removePropertyChangeListener(this);
+	}
+
+	private void setInput(Simulation simulation) {
+		if (treeViewer != null && !treeViewer.getControl().isDisposed()) {
+			treeViewer.setInput(BMotionEditorPlugin.getOpenSimulations()
+					.values());
+			treeViewer.expandAll();
+		}
+	}
+
+	@Override
+	public void commandStackChanged(EventObject event) {
+		treeViewer.refresh();
+	}
+
+	private class ControlLabelProvider implements ITableLabelProvider,
+			ITableColorProvider {
+
+		@Override
+		public void addListener(ILabelProviderListener listener) {
+			// TODO Auto-generated method stub
+
+		}
+
+		@Override
+		public void dispose() {
+			// TODO Auto-generated method stub
+
+		}
+
+		@Override
+		public boolean isLabelProperty(Object element, String property) {
+			// TODO Auto-generated method stub
+			return false;
+		}
+
+		@Override
+		public void removeListener(ILabelProviderListener listener) {
+			// TODO Auto-generated method stub
+
+		}
+
+		@Override
+		public Color getForeground(Object element, int columnIndex) {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public Color getBackground(Object element, int columnIndex) {
+			switch (columnIndex) {
+			case 1:
+				if (element instanceof Simulation) {
+					Simulation simulation = (Simulation) element;
+					if (simulation.isDirty())
+						return ColorConstants.red;
+					else
+						return ColorConstants.green;
+
+				}
+			}
+			return null;
+		}
+
+		@Override
+		public Image getColumnImage(Object element, int columnIndex) {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public String getColumnText(Object element, int columnIndex) {
+			switch (columnIndex) {
+			case 0:
+				if (element instanceof Simulation) {
+					Simulation simulation = (Simulation) element;
+					String prefix = "";
+					if (simulation.isDirty())
+						prefix = "* ";
+					return prefix
+							+ ((Simulation) element).getProjectFile().getName();
+				} else if (element instanceof VisualizationView)
+					return ((VisualizationView) element).getName();
+			}
+			return null;
+		}
+
+	}
+
+	@Override
+	public void propertyChange(PropertyChangeEvent evt) {
+		if (evt.getPropertyName().equals("dirty"))
+			treeViewer.refresh();
+	}
+
+}
diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/SaveSimulationAction.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/SaveSimulationAction.java
new file mode 100644
index 00000000..21dbdf43
--- /dev/null
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/controlpanel/SaveSimulationAction.java
@@ -0,0 +1,118 @@
+/** 
+ * (c) 2009 Lehrstuhl fuer Softwaretechnik und Programmiersprachen, 
+ * Heinrich Heine Universitaet Duesseldorf
+ * This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html) 
+ * */
+
+package de.bmotionstudio.gef.editor.controlpanel;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.IPerspectiveRegistry;
+import org.eclipse.ui.PlatformUI;
+
+import com.thoughtworks.xstream.XStream;
+
+import de.bmotionstudio.gef.editor.BMotionEditorPlugin;
+import de.bmotionstudio.gef.editor.BMotionStudioImage;
+import de.bmotionstudio.gef.editor.model.Simulation;
+import de.bmotionstudio.gef.editor.util.PerspectiveUtil;
+
+public class SaveSimulationAction extends Action {
+
+	private TreeViewer viewer;
+
+	public SaveSimulationAction(TreeViewer viewer) {
+		this.viewer = viewer;
+		setText("Save Simulation");
+		setImageDescriptor(BMotionStudioImage.getImageDescriptor(
+				"org.eclipse.ui", "$nl$/icons/full/etool16/save_edit.gif"));
+	}
+
+	@Override
+	public void run() {
+
+		IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
+		Object firstElement = sel.getFirstElement();
+		if (firstElement instanceof Simulation) {
+
+			Simulation simulation = (Simulation) firstElement;
+
+			IPerspectiveRegistry perspectiveRegistry = PlatformUI
+					.getWorkbench().getPerspectiveRegistry();
+
+			String perspectiveId = PerspectiveUtil
+					.getPerspectiveIdFromFile(simulation.getProjectFile());
+			IPerspectiveDescriptor perspectiveDescriptor = perspectiveRegistry
+					.findPerspectiveWithId(perspectiveId);
+			if (perspectiveDescriptor != null) {
+				PlatformUI.getWorkbench().getActiveWorkbenchWindow()
+						.getActivePage()
+						.savePerspectiveAs(perspectiveDescriptor);
+				PerspectiveUtil.exportPerspective(simulation,
+						perspectiveDescriptor);
+			}
+
+			ByteArrayOutputStream out = new ByteArrayOutputStream();
+			OutputStreamWriter writer = null;
+			try {
+				// saveProperties();
+				writer = new OutputStreamWriter(out, "UTF8");
+				XStream xstream = new XStream();
+				BMotionEditorPlugin.setAliases(xstream);
+				xstream.toXML(simulation, writer);
+				IFile file = simulation.getProjectFile();
+				file.setContents(new ByteArrayInputStream(out.toByteArray()),
+						true, false, new NullProgressMonitor());
+				// getCommandStack().markSaveLocation();
+				simulation.setDirty(false);
+				viewer.refresh();
+			} catch (CoreException ce) {
+				ce.printStackTrace();
+			} catch (IOException ioe) {
+				ioe.printStackTrace();
+			} finally {
+				try {
+					out.close();
+					if (writer != null)
+						writer.close();
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			}
+
+
+			// IWorkbench workbench = PlatformUI.getWorkbench();
+			// IWorkbenchPage page = workbench.getActiveWorkbenchWindow()
+			// .getActivePage();
+			//
+			// IPerspectiveRegistry perspectiveRegistry = workbench
+			// .getPerspectiveRegistry();
+			//
+			// Simulation simulation = (Simulation) firstElement;
+			// String perspectiveId = PerspectiveUtil
+			// .getPerspectiveIdFromFile(simulation.getProjectFile());
+			// IPerspectiveDescriptor perspectiveDescriptor =
+			// perspectiveRegistry.findPerspectiveWithId(perspectiveId);
+			// if(perspectiveDescriptor != null) {
+			// PerspectiveUtil.closePerspective(page, perspectiveDescriptor);
+			// PerspectiveUtil.deletePerspective(page, perspectiveDescriptor);
+			// }
+			//
+			// BMotionEditorPlugin.closeSimulation(simulation);
+
+		}
+
+	}
+
+}
diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/util/PerspectiveUtil.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/util/PerspectiveUtil.java
new file mode 100644
index 00000000..a8fbc759
--- /dev/null
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/util/PerspectiveUtil.java
@@ -0,0 +1,149 @@
+package de.bmotionstudio.gef.editor.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.preferences.IPreferenceFilter;
+import org.eclipse.core.runtime.preferences.IPreferencesService;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.core.runtime.preferences.PreferenceFilterEntry;
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.IPerspectiveRegistry;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.WorkbenchException;
+
+import de.bmotionstudio.gef.editor.VisualizationViewPart;
+import de.bmotionstudio.gef.editor.model.Simulation;
+import de.bmotionstudio.gef.editor.model.VisualizationView;
+import de.prob.logging.Logger;
+
+public class PerspectiveUtil {
+
+	public static void deletePerspective(IWorkbenchPage page,
+			IPerspectiveDescriptor perspectiveDescriptor) {
+		if (perspectiveDescriptor == null || page == null)
+			return;
+		IPerspectiveRegistry perspectiveRegistry = page.getWorkbenchWindow()
+				.getWorkbench().getPerspectiveRegistry();
+		perspectiveRegistry.deletePerspective(perspectiveDescriptor);
+	}
+
+	public static void closePerspective(IWorkbenchPage page,
+			IPerspectiveDescriptor perspectiveDescriptor) {
+		if (perspectiveDescriptor == null || page == null)
+			return;
+		page.closePerspective(perspectiveDescriptor, false, true);
+	}
+
+	public static void switchPerspective(
+			IPerspectiveDescriptor perspectiveDescriptor) {
+		switchPerspective(perspectiveDescriptor.getId());
+	}
+
+	public static void switchPerspective(String perspectiveID) {
+		IWorkbench workbench = PlatformUI.getWorkbench();
+		try {
+			workbench.showPerspective(perspectiveID,
+					workbench.getActiveWorkbenchWindow());
+		} catch (WorkbenchException e) {
+			Logger.notifyUser(
+					"An error occured while trying to switch the perspective.",
+					e);
+		}
+	}
+
+	public static void exportPerspective(final Simulation simulation,
+			final IPerspectiveDescriptor perspectiveDescriptor) {
+
+		Assert.isNotNull(perspectiveDescriptor);
+		Assert.isNotNull(simulation);
+
+		FileOutputStream fos = null;
+
+		try {
+
+			IPreferenceFilter[] transfers = null;
+
+			transfers = new IPreferenceFilter[1];
+
+			// For export all create a preference filter that can export
+			// all nodes of the Instance and Configuration scopes
+			transfers[0] = new IPreferenceFilter() {
+				public String[] getScopes() {
+					return new String[] { InstanceScope.SCOPE };
+				}
+
+				public Map<String, PreferenceFilterEntry[]> getMapping(
+						String scope) {
+					Map<String, PreferenceFilterEntry[]> map = new HashMap<String, PreferenceFilterEntry[]>();
+					map.put("org.eclipse.ui.workbench",
+							new PreferenceFilterEntry[] { new PreferenceFilterEntry(
+									perspectiveDescriptor.getId() + "_persp") });
+					return map;
+				}
+			};
+
+			IFile pFile = simulation
+					.getProjectFile()
+					.getProject()
+					.getFile(
+							simulation.getProjectFile().getName()
+									.replace(".bmso", ".bmsop"));
+
+			String content = "";
+
+			if (!pFile.exists())
+				pFile.create(new ByteArrayInputStream(content.getBytes()),
+						true, new NullProgressMonitor());
+
+			File exportFile = new File(pFile.getLocationURI());
+			fos = new FileOutputStream(exportFile);
+			IPreferencesService service = Platform.getPreferencesService();
+			service.exportPreferences(service.getRootNode(), transfers, fos);
+
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		} catch (CoreException e) {
+			e.printStackTrace();
+		} finally {
+			try {
+				if (fos != null)
+					fos.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+
+	}
+
+	public static String getPerspectiveIdFromFile(IFile file) {
+		return "BMS_" + file.getName().replace(".bmso", "");
+	}
+
+	public static VisualizationViewPart createVisualizationViewPart(
+			String secId, VisualizationView visualizationView)
+			throws PartInitException {
+		IWorkbenchWindow window = PlatformUI.getWorkbench()
+				.getActiveWorkbenchWindow();
+		IWorkbenchPage activePage = window.getActivePage();
+		VisualizationViewPart visualizationViewPart = (VisualizationViewPart) activePage
+				.showView(VisualizationViewPart.ID, secId,
+						IWorkbenchPage.VIEW_VISIBLE);
+		return visualizationViewPart;
+	}
+
+}
-- 
GitLab