Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWojciech Sudol2015-10-15 12:33:59 +0000
committerWojciech Sudol2015-11-19 18:31:29 +0000
commit807e99692a618dde238605b07c75084a29137d60 (patch)
treef0fbbbeb9176d57b59c4f69b19b81c5a347b419d
parentf65b8ec46aa711e2e1b4960250a9222c11943b5f (diff)
downloadeclipse.platform.ui-807e99692a618dde238605b07c75084a29137d60.tar.gz
eclipse.platform.ui-807e99692a618dde238605b07c75084a29137d60.tar.xz
eclipse.platform.ui-807e99692a618dde238605b07c75084a29137d60.zip
Bug 378811 - [Perspectives] Can't export and import perspectives anymore
Backporting the Perspective import export changes to Eclipse 4.4.2 Change-Id: Id58520b5014790abd66024a7318d04f777244f65 Also-by: Kalyan Prasad <kalyan_prasad@in.ibm.com>
-rw-r--r--bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF3
-rw-r--r--bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java43
-rw-r--r--bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ModeledPageLayout.java109
-rw-r--r--bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ModeledPageLayoutUtils.java124
-rw-r--r--bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/InfoReader.java145
-rw-r--r--bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/MementoReader.java69
-rw-r--r--bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/PerspectiveBuilder.java683
-rw-r--r--bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/PerspectiveReader.java336
-rw-r--r--bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/registry/ImportExportPespectiveHandler.java362
-rw-r--r--bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/registry/PerspectiveRegistry.java55
-rw-r--r--bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/wizards/preferences/PreferencesExportWizard.java23
-rw-r--r--bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/wizards/preferences/PreferencesImportWizard.java20
-rw-r--r--bundles/org.eclipse.ui.workbench/META-INF/MANIFEST.MF4
13 files changed, 1865 insertions, 111 deletions
diff --git a/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF
index 26b1b711fcd..eeedc6f44bc 100644
--- a/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF
@@ -21,7 +21,8 @@ Require-Bundle: org.eclipse.e4.ui.model.workbench;bundle-version="1.0.0",
org.eclipse.core.expressions;bundle-version="[3.4.200,4.0.0)",
org.eclipse.e4.ui.di;bundle-version="0.9.0",
org.eclipse.emf.ecore.xmi;bundle-version="2.7.0",
- org.eclipse.e4.core.di.extensions
+ org.eclipse.e4.core.di.extensions,
+ org.eclipse.jface;bundle-version="3.10.2"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Export-Package: org.eclipse.e4.ui.internal.workbench;
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java
index 99a9e30b848..121b0d0ee59 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2010, 2014 IBM Corporation and others.
+ * Copyright (c) 2010, 2015 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
@@ -59,6 +59,7 @@ import org.eclipse.e4.ui.workbench.modeling.EPlaceholderResolver;
import org.eclipse.e4.ui.workbench.modeling.ElementMatcher;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.jface.resource.ImageDescriptor;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
@@ -68,6 +69,10 @@ import org.osgi.service.event.EventHandler;
public class ModelServiceImpl implements EModelService {
private static String HOSTED_ELEMENT = "HostedElement"; //$NON-NLS-1$
+ private static final String COMPATIBILITY_VIEW_URI = "bundleclass://org.eclipse.ui.workbench/org.eclipse.ui.internal.e4.compatibility.CompatibilityView"; //$NON-NLS-1$
+
+ private static final String TAG_LABEL = "label"; //$NON-NLS-1$
+
private IEclipseContext appContext;
/** Factory which is able to create {@link MApplicationElement}s in a generic way. */
@@ -413,14 +418,50 @@ public class ModelServiceImpl implements EModelService {
EPlaceholderResolver resolver = appContext.get(EPlaceholderResolver.class);
// Re-resolve any placeholder references
List<MPlaceholder> phList = findElements(element, null, MPlaceholder.class, null);
+ List<MPlaceholder> unresolved = new ArrayList<MPlaceholder>();
for (MPlaceholder ph : phList) {
resolver.resolvePlaceholderRef(ph, refWin);
+ if (ph.getRef() == null) {
+ unresolved.add(ph);
+ }
+ }
+ for (MPlaceholder ph : unresolved) {
+ replacePlaceholder(ph);
}
}
return element;
}
+ private void replacePlaceholder(MPlaceholder ph) {
+ MPart part = createModelElement(MPart.class);
+ part.setElementId(ph.getElementId());
+ part.getTransientData().put(IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY,
+ ImageDescriptor.getMissingImageDescriptor().createImage());
+ String label = (String) ph.getTransientData().get(TAG_LABEL);
+ if (label != null) {
+ part.setLabel(label);
+ } else {
+ part.setLabel(getLabel(ph.getElementId()));
+ }
+ part.setContributionURI(COMPATIBILITY_VIEW_URI);
+ part.setCloseable(true);
+ MElementContainer<MUIElement> curParent = ph.getParent();
+ int curIndex = curParent.getChildren().indexOf(ph);
+ curParent.getChildren().remove(curIndex);
+ curParent.getChildren().add(curIndex, part);
+ if (curParent.getSelectedElement() == ph) {
+ curParent.setSelectedElement(part);
+ }
+ }
+
+ private String getLabel(String str) {
+ int index = str.lastIndexOf('.');
+ if (index == -1)
+ return str;
+ return str.substring(index + 1);
+ }
+
@Override
public MUIElement findSnippet(MSnippetContainer snippetContainer, String id) {
if (snippetContainer == null || id == null || id.length() == 0) {
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ModeledPageLayout.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ModeledPageLayout.java
index b5c34c7343c..0ccb3de2418 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ModeledPageLayout.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ModeledPageLayout.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2013 IBM Corporation and others.
+ * Copyright (c) 2009, 2015 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
@@ -23,7 +23,6 @@ import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
import org.eclipse.e4.ui.model.application.ui.advanced.impl.AdvancedFactoryImpl;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
-import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.model.application.ui.basic.MStackElement;
@@ -33,7 +32,6 @@ import org.eclipse.e4.ui.workbench.IPresentationEngine;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.osgi.util.NLS;
-import org.eclipse.swt.SWT;
import org.eclipse.ui.IFolderLayout;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveDescriptor;
@@ -61,6 +59,7 @@ public class ModeledPageLayout implements IPageLayout {
public static final String PERSP_SHORTCUT_TAG = "persp.perspSC:"; //$NON-NLS-1$
public static final String SHOW_IN_PART_TAG = "persp.showIn:"; //$NON-NLS-1$
public static final String SHOW_VIEW_TAG = "persp.viewSC:"; //$NON-NLS-1$
+ public static final String EDITOR_STACK_TAG = "EditorStack"; //$NON-NLS-1$
public static final String HIDDEN_MENU_PREFIX = "persp.hideMenuSC:"; //$NON-NLS-1$
public static final String HIDDEN_TOOLBAR_PREFIX = "persp.hideToolbarSC:"; //$NON-NLS-1$
public static final String HIDDEN_ITEMS_KEY = "persp.hiddenItems"; //$NON-NLS-1$
@@ -95,6 +94,8 @@ public class ModeledPageLayout implements IPageLayout {
private IViewRegistry viewRegistry;
+ private ModeledPageLayoutUtils layoutUtils;
+
private class ViewActivator implements IIdentifierListener {
private MUIElement element;
@@ -138,6 +139,7 @@ public class ModeledPageLayout implements IPageLayout {
// Create the editor area stack
this.perspModel = perspModel;
this.descriptor = descriptor;
+ this.layoutUtils = new ModeledPageLayoutUtils(modelService);
this.createReferences = createReferences;
@@ -158,7 +160,7 @@ public class ModeledPageLayout implements IPageLayout {
// temporary HACK for bug 303982
editorStack.getTags().add("newtablook"); //$NON-NLS-1$
editorStack.getTags().add("org.eclipse.e4.primaryDataStack"); //$NON-NLS-1$
- editorStack.getTags().add("EditorStack"); //$NON-NLS-1$
+ editorStack.getTags().add(EDITOR_STACK_TAG);
editorStack.setElementId("org.eclipse.e4.primaryDataStack"); //$NON-NLS-1$
sharedArea.getChildren().add(editorStack);
sharedArea.setElementId(getEditorArea());
@@ -374,21 +376,6 @@ public class ModeledPageLayout implements IPageLayout {
// perspModel.setFixed(isFixed);
}
- private static int plRelToSwt(int rel) {
- switch (rel) {
- case IPageLayout.BOTTOM:
- return SWT.BOTTOM;
- case IPageLayout.LEFT:
- return SWT.LEFT;
- case IPageLayout.RIGHT:
- return SWT.RIGHT;
- case IPageLayout.TOP:
- return SWT.TOP;
- default:
- return 0;
- }
- }
-
public static MStackElement createViewModel(MApplication application, String id,
boolean visible,
WorkbenchPage page, EPartService partService, boolean createReferences) {
@@ -418,15 +405,6 @@ public class ModeledPageLayout implements IPageLayout {
return null;
}
- public static MPartStack createStack(String id, boolean visible) {
- MPartStack newStack = BasicFactoryImpl.eINSTANCE.createPartStack();
- // temporary HACK for bug 303982
- newStack.getTags().add("newtablook"); //$NON-NLS-1$
- newStack.setElementId(id);
- newStack.setToBeRendered(visible);
- return newStack;
- }
-
private MUIElement insertView(String viewId, int relationship, float ratio,
String refId, boolean visible, boolean withStack) {
@@ -446,7 +424,8 @@ public class ModeledPageLayout implements IPageLayout {
stack.getChildren().add(viewModel);
retVal = stack;
} else {
- insert(viewModel, findRefModel(refId), plRelToSwt(relationship), ratio);
+ layoutUtils.insert(viewModel, findRefModel(refId),
+ layoutUtils.plRelToSwt(relationship), ratio);
}
}
@@ -508,8 +487,9 @@ public class ModeledPageLayout implements IPageLayout {
MUIElement refModel = findElement(perspModel, refId);
if (refModel == null) {
WorkbenchPlugin.log(NLS.bind(WorkbenchMessages.PageLayout_missingRefPart, refId));
- MPartStack stack = createStack(stackId, visible);
- insert(stack, getLastElement(), plRelToSwt(relationship), ratio);
+ MPartStack stack = layoutUtils.createStack(stackId, visible);
+ layoutUtils
+ .insert(stack, getLastElement(), layoutUtils.plRelToSwt(relationship), ratio);
return stack;
}
// If the 'refModel' is -not- a stack then find one
@@ -526,13 +506,13 @@ public class ModeledPageLayout implements IPageLayout {
// return null;
// }
- MPartStack stack = createStack(stackId, visible);
+ MPartStack stack = layoutUtils.createStack(stackId, visible);
MElementContainer<?> parent = refModel.getParent();
if (parent instanceof MPartStack) {
// we don't want to put a stack in a stack
refModel = parent;
}
- insert(stack, refModel, plRelToSwt(relationship), ratio);
+ layoutUtils.insert(stack, refModel, layoutUtils.plRelToSwt(relationship), ratio);
return stack;
}
@@ -568,69 +548,6 @@ public class ModeledPageLayout implements IPageLayout {
newParent.getChildren().add(relTo);
}
- public static void insert(MUIElement toInsert, MUIElement relTo,
- int swtSide, int ratio) {
- if (toInsert == null || relTo == null)
- return;
-
- MElementContainer<MUIElement> relParent = relTo.getParent();
- if (relParent != null) {
- List<MUIElement> children = relParent.getChildren();
- int index = children.indexOf(relTo);
- MPartSashContainer psc = BasicFactoryImpl.eINSTANCE.createPartSashContainer();
- psc.setContainerData(relTo.getContainerData());
- relParent.getChildren().add(index + 1, psc);
-
- switch (swtSide) {
- case SWT.LEFT:
- psc.getChildren().add((MPartSashContainerElement) toInsert);
- psc.getChildren().add((MPartSashContainerElement) relTo);
- toInsert.setContainerData("" + ratio); //$NON-NLS-1$
- relTo.setContainerData("" + (10000 - ratio)); //$NON-NLS-1$
- psc.setHorizontal(true);
- break;
- case SWT.RIGHT:
- psc.getChildren().add((MPartSashContainerElement) relTo);
- psc.getChildren().add((MPartSashContainerElement) toInsert);
- relTo.setContainerData("" + ratio); //$NON-NLS-1$
- toInsert.setContainerData("" + (10000 - ratio)); //$NON-NLS-1$
- psc.setHorizontal(true);
- break;
- case SWT.TOP:
- psc.getChildren().add((MPartSashContainerElement) toInsert);
- psc.getChildren().add((MPartSashContainerElement) relTo);
- toInsert.setContainerData("" + ratio); //$NON-NLS-1$
- relTo.setContainerData("" + (10000 - ratio)); //$NON-NLS-1$
- psc.setHorizontal(false);
- break;
- case SWT.BOTTOM:
- psc.getChildren().add((MPartSashContainerElement) relTo);
- psc.getChildren().add((MPartSashContainerElement) toInsert);
- relTo.setContainerData("" + ratio); //$NON-NLS-1$
- toInsert.setContainerData("" + (10000 - ratio)); //$NON-NLS-1$
- psc.setHorizontal(false);
- break;
- }
-
- if (relTo.isToBeRendered() || toInsert.isToBeRendered()) {
- // one of the items to be inserted should be rendered, render
- // all parent elements as well
- resetToBeRenderedFlag(psc, true);
- } else {
- // no child elements need to be rendered, the parent part sash
- // container does not need to be rendered either then
- psc.setToBeRendered(false);
- }
- return;
- }
- }
-
- public static void insert(MUIElement toInsert, MUIElement relTo,
- int swtSide, float ratio) {
- int pct = (int) (ratio * 10000);
- insert(toInsert, relTo, swtSide, pct);
- }
-
MUIElement findElement(MUIElement toSearch, String id) {
List<Object> found = modelService.findElements(toSearch, id, null, null,
EModelService.IN_ANY_PERSPECTIVE);
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ModeledPageLayoutUtils.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ModeledPageLayoutUtils.java
new file mode 100644
index 00000000000..a3115ac8fc6
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/compatibility/ModeledPageLayoutUtils.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2015 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.ui.internal.e4.compatibility;
+
+import java.util.List;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.swt.SWT;
+import org.eclipse.ui.IPageLayout;
+
+public class ModeledPageLayoutUtils {
+
+ private EModelService modelService;
+
+ public ModeledPageLayoutUtils(EModelService modelService) {
+ this.modelService = modelService;
+ }
+
+ public int plRelToSwt(int rel) {
+ switch (rel) {
+ case IPageLayout.BOTTOM:
+ return SWT.BOTTOM;
+ case IPageLayout.LEFT:
+ return SWT.LEFT;
+ case IPageLayout.RIGHT:
+ return SWT.RIGHT;
+ case IPageLayout.TOP:
+ return SWT.TOP;
+ default:
+ return 0;
+ }
+ }
+
+ public void insert(MUIElement toInsert, MUIElement relTo, int swtSide, float ratio) {
+ int pct = (int) (ratio * 10000);
+ insert(toInsert, relTo, swtSide, pct);
+ }
+
+ public void insert(MUIElement toInsert, MUIElement relTo, int swtSide, int ratio) {
+ if (toInsert == null || relTo == null)
+ return;
+
+ MElementContainer<MUIElement> relParent = relTo.getParent();
+ if (relParent != null) {
+ List<MUIElement> children = relParent.getChildren();
+ int index = children.indexOf(relTo);
+ MPartSashContainer psc = modelService.createModelElement(MPartSashContainer.class);
+ psc.setContainerData(relTo.getContainerData());
+ relParent.getChildren().add(index + 1, psc);
+
+ switch (swtSide) {
+ case SWT.LEFT:
+ psc.getChildren().add((MPartSashContainerElement) toInsert);
+ psc.getChildren().add((MPartSashContainerElement) relTo);
+ toInsert.setContainerData("" + ratio); //$NON-NLS-1$
+ relTo.setContainerData("" + (10000 - ratio)); //$NON-NLS-1$
+ psc.setHorizontal(true);
+ break;
+ case SWT.RIGHT:
+ psc.getChildren().add((MPartSashContainerElement) relTo);
+ psc.getChildren().add((MPartSashContainerElement) toInsert);
+ relTo.setContainerData("" + ratio); //$NON-NLS-1$
+ toInsert.setContainerData("" + (10000 - ratio)); //$NON-NLS-1$
+ psc.setHorizontal(true);
+ break;
+ case SWT.TOP:
+ psc.getChildren().add((MPartSashContainerElement) toInsert);
+ psc.getChildren().add((MPartSashContainerElement) relTo);
+ toInsert.setContainerData("" + ratio); //$NON-NLS-1$
+ relTo.setContainerData("" + (10000 - ratio)); //$NON-NLS-1$
+ psc.setHorizontal(false);
+ break;
+ case SWT.BOTTOM:
+ psc.getChildren().add((MPartSashContainerElement) relTo);
+ psc.getChildren().add((MPartSashContainerElement) toInsert);
+ relTo.setContainerData("" + ratio); //$NON-NLS-1$
+ toInsert.setContainerData("" + (10000 - ratio)); //$NON-NLS-1$
+ psc.setHorizontal(false);
+ break;
+ }
+
+ if (relTo.isToBeRendered() || toInsert.isToBeRendered()) {
+ // one of the items to be inserted should be rendered, render
+ // all parent elements as well
+ resetToBeRenderedFlag(psc, true);
+ } else {
+ // no child elements need to be rendered, the parent part sash
+ // container does not need to be rendered either then
+ psc.setToBeRendered(false);
+ }
+ return;
+ }
+ }
+
+ public void resetToBeRenderedFlag(MUIElement element, boolean toBeRendered) {
+ MUIElement parent = element.getParent();
+ while (parent != null && !(parent instanceof MPerspective)) {
+ parent.setToBeRendered(toBeRendered);
+ parent = parent.getParent();
+ }
+ element.setToBeRendered(toBeRendered);
+ }
+
+ public MPartStack createStack(String id, boolean visible) {
+ MPartStack newStack = modelService.createModelElement(MPartStack.class);
+ newStack.setElementId(id);
+ newStack.setToBeRendered(visible);
+ return newStack;
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/InfoReader.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/InfoReader.java
new file mode 100644
index 00000000000..1a02538099a
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/InfoReader.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2015 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.ui.internal.e4.migration;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.internal.IWorkbenchConstants;
+
+public class InfoReader extends MementoReader {
+
+ private List<PageReader> pages;
+
+ private IMemento memFolder;
+
+ InfoReader(IMemento memento) {
+ super(memento);
+ }
+
+ String getId() {
+ return getString(IWorkbenchConstants.TAG_PART);
+ }
+
+ boolean isRelativelyPositioned() {
+ return contains(IWorkbenchConstants.TAG_RATIO);
+ }
+
+ boolean isFolder() {
+ return getBoolean(IWorkbenchConstants.TAG_FOLDER);
+ }
+
+ boolean isEditorArea() {
+ String id = getId();
+ return IPageLayout.ID_EDITOR_AREA.equals(id);
+ }
+
+ private IMemento getFolder() {
+ if (memFolder == null) {
+ memFolder = memento.getChild(IWorkbenchConstants.TAG_FOLDER);
+ }
+ return memFolder;
+ }
+
+ int[] getPartOrder() {
+ IMemento folder = getFolder();
+ if (folder == null) {
+ return null;
+ }
+
+ IMemento presentation = folder.getChild(IWorkbenchConstants.TAG_PRESENTATION);
+ if (presentation == null) {
+ return null;
+ }
+
+ IMemento[] partPositions = presentation.getChildren(IWorkbenchConstants.TAG_PART);
+ int[] partOrder = new int[partPositions.length];
+ for (int i = 0; i < partPositions.length; i++) {
+ partOrder[i] = partPositions[i].getInteger(IWorkbenchConstants.TAG_ID);
+ }
+ return partOrder;
+ }
+
+ List<PageReader> getPages() {
+ if (pages != null) {
+ return pages;
+ }
+
+ IMemento folder = getFolder();
+ if (folder != null) {
+ IMemento[] pageMems = folder.getChildren(IWorkbenchConstants.TAG_PAGE);
+ pages = new ArrayList<PageReader>(pageMems.length);
+ for (IMemento pageMem : pageMems) {
+ pages.add(new PageReader(pageMem));
+ }
+ }
+ return pages;
+ }
+
+ String getActivePageId() {
+ String activePageId = null;
+ IMemento folder = getFolder();
+ if (folder != null) {
+ activePageId = folder.getString(IWorkbenchConstants.TAG_ACTIVE_PAGE_ID);
+ }
+ return activePageId;
+ }
+
+ float getRatio() {
+ return getFloat(IWorkbenchConstants.TAG_RATIO);
+ }
+
+ int getRelationship() {
+ return getInteger(IWorkbenchConstants.TAG_RELATIONSHIP);
+ }
+
+ String getRelative() {
+ return getString(IWorkbenchConstants.TAG_RELATIVE);
+ }
+
+ public PartState getState() {
+ PartState state = PartState.RESTORED;
+ IMemento folder = getFolder();
+ int value = folder.getInteger(IWorkbenchConstants.TAG_EXPANDED);
+ switch (value) {
+ case 0:
+ state = PartState.MINIMIZED;
+ break;
+ case 1:
+ state = PartState.MAXIMIZED;
+ break;
+ }
+ return state;
+ }
+
+ public static enum PartState {
+ MINIMIZED, MAXIMIZED, RESTORED;
+ }
+
+ static class PageReader extends MementoReader {
+
+ PageReader(IMemento pageMemento) {
+ super(pageMemento);
+ }
+
+ String getId() {
+ return getString(IWorkbenchConstants.TAG_CONTENT);
+ }
+
+ String getLabel() {
+ return getString(IWorkbenchConstants.TAG_LABEL);
+ }
+
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/MementoReader.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/MementoReader.java
new file mode 100644
index 00000000000..af3dea63df9
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/MementoReader.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2015 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.ui.internal.e4.migration;
+
+import java.util.Arrays;
+import org.eclipse.ui.IMemento;
+
+public class MementoReader {
+
+ protected IMemento memento;
+
+ MementoReader() {
+ }
+
+ MementoReader(IMemento memento) {
+ this.memento = memento;
+ }
+
+ protected String getString(String attribute) {
+ return memento.getString(attribute);
+ }
+
+ /**
+ * @param attribute
+ * @return value or false when attribute not found
+ */
+ protected boolean getBoolean(String attribute) {
+ return Boolean.TRUE.equals(memento.getBoolean(attribute));
+ }
+
+ protected boolean getBoolean(String attribute, boolean defaultValue) {
+ Boolean value = memento.getBoolean(attribute);
+ return value == null ? defaultValue : value;
+ }
+
+ protected Integer getInteger(String attribute) {
+ return memento.getInteger(attribute);
+ }
+
+ protected Float getFloat(String attribute) {
+ return memento.getFloat(attribute);
+ }
+
+ protected boolean contains(String attribute) {
+ return Arrays.asList(memento.getAttributeKeys()).contains(attribute);
+ }
+
+ protected IMemento[] getChildren(String tagName) {
+ return memento.getChildren(tagName);
+ }
+
+ protected IMemento getChild(String tagName) {
+ return memento.getChild(tagName);
+ }
+
+ IMemento getMemento() {
+ return memento;
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/PerspectiveBuilder.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/PerspectiveBuilder.java
new file mode 100644
index 00000000000..4bd68038aff
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/PerspectiveBuilder.java
@@ -0,0 +1,683 @@
+/*******************************************************************************
+ * Copyright (c) 2015 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.ui.internal.e4.migration;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.SideValue;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainer;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartSashContainerElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
+import org.eclipse.e4.ui.model.application.ui.basic.MStackElement;
+import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow;
+import org.eclipse.e4.ui.workbench.IPresentationEngine;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.internal.IWorkbenchConstants;
+import org.eclipse.ui.internal.PerspectiveTagger;
+import org.eclipse.ui.internal.e4.compatibility.ModeledPageLayout;
+import org.eclipse.ui.internal.e4.compatibility.ModeledPageLayoutUtils;
+import org.eclipse.ui.internal.e4.migration.InfoReader.PageReader;
+import org.eclipse.ui.internal.e4.migration.InfoReader.PartState;
+import org.eclipse.ui.internal.e4.migration.PerspectiveReader.DetachedWindowReader;
+import org.eclipse.ui.internal.e4.migration.PerspectiveReader.ViewLayoutReader;
+import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
+import org.eclipse.ui.internal.registry.RegistryReader;
+import org.eclipse.ui.internal.registry.StickyViewDescriptor;
+
+public class PerspectiveBuilder {
+
+ static final String ORIGINAL_ID = "originalId"; //$NON-NLS-1$
+
+ static final String BASE_PERSPECTIVE_ID = "basePerspectiveId"; //$NON-NLS-1$
+
+ private static final String DEFAULT_FASTVIEW_STACK = "defaultFastViewStack"; //$NON-NLS-1$
+
+ private static final String ID_EDITOR_AREA = IPageLayout.ID_EDITOR_AREA;
+
+ @Inject
+ private PerspectiveReader perspReader;
+
+ @Inject
+ private EModelService modelService;
+
+ private MPerspective perspective;
+
+ private List<String> tags;
+
+ private List<String> renderedViews;
+
+ private List<String> defaultFastViews;
+
+ private Map<String, MPlaceholder> viewPlaceholders = new HashMap<String, MPlaceholder>();
+
+ private Map<String, ViewLayoutReader> viewLayouts;
+
+ private MPlaceholder editorAreaPlaceholder;
+
+ private ModeledPageLayoutUtils layoutUtils;
+
+ @PostConstruct
+ private void postConstruct() {
+ layoutUtils = new ModeledPageLayoutUtils(modelService);
+ }
+
+ public MPerspective createPerspective() {
+ create();
+ tags = perspective.getTags();
+ populate();
+ return perspective;
+ }
+
+ private void create() {
+ perspective = modelService.createModelElement(MPerspective.class);
+ perspective.setElementId(perspReader.getId());
+ String label = perspReader.getLabel();
+ perspective.setLabel(label);
+ perspective.setTooltip(label);
+ if (perspReader.isCustom()) {
+ perspective.getTransientData().put(BASE_PERSPECTIVE_ID, perspReader.getBasicPerspectiveId());
+ perspective.getTransientData().put(ORIGINAL_ID, perspReader.getOriginalId());
+ }
+ }
+
+ private void populate() {
+ addActionSetTags();
+ addPerspectiveShortcutTags();
+ addNewWizardTags();
+ addShowViewTags();
+ addHiddenItems();
+ addShowInTags();
+
+ for (InfoReader info : perspReader.getInfos()) {
+ if (info.isEditorArea()) {
+ addEditorArea(info);
+ } else if (info.isFolder()) {
+ MPartStack stack = addPartStack(info);
+ populatePartStack(stack, info);
+ }
+ }
+
+ addDefaultFastViewStack();
+ setZoomState();
+ addDetachedWindows();
+ hideEmptyStacks();
+ hideUrenderableSashes();
+ hideInvisibleSashes();
+ processStandaloneViews();
+ correctSelectedElements();
+ addTrimBars();
+ PerspectiveTagger.tagPerspective(perspective, modelService);
+ }
+
+ private void processStandaloneViews() {
+ Map<String, ViewLayoutReader> viewLayouts = perspReader.getViewLayouts();
+ for (String viewId : viewLayouts.keySet()) {
+ MPlaceholder placeholder = viewPlaceholders.get(viewId);
+ if (placeholder == null) {
+ continue;
+ }
+ if (viewLayouts.get(viewId).isStandalone()) {
+ MElementContainer<MUIElement> parent = placeholder.getParent();
+ placeholder.setContainerData(parent.getContainerData());
+ parent.getChildren().remove(placeholder);
+ MElementContainer<MUIElement> grandParent = parent.getParent();
+ int location = grandParent.getChildren().indexOf(parent);
+ grandParent.getChildren().add(location, placeholder);
+ grandParent.getChildren().remove(parent);
+ }
+ }
+ }
+
+ private void addDetachedWindows() {
+ for (DetachedWindowReader detachedWindowReader : perspReader.getDetachedWindows()) {
+ MTrimmedWindow detachedWindow = modelService.createModelElement(MTrimmedWindow.class);
+ Rectangle bounds = detachedWindowReader.getBounds();
+ detachedWindow.setX(bounds.x);
+ detachedWindow.setY(bounds.y);
+ detachedWindow.setWidth(bounds.width);
+ detachedWindow.setHeight(bounds.height);
+ MPartStack stack = modelService.createModelElement(MPartStack.class);
+ populatePartStack(stack, detachedWindowReader);
+ detachedWindow.getChildren().add(stack);
+ perspective.getWindows().add(detachedWindow);
+ }
+ }
+
+ private void addTrimBars() {
+ Map<String, Integer> fastViewBars = perspReader.getFastViewBars();
+ if (fastViewBars.size() == 0 && defaultFastViews.size() == 0) {
+ return;
+ }
+
+ int topCounter = 0;
+ int bottomCounter = 0;
+ int rightCounter = 0;
+ int leftCounter = 0;
+ StringBuilder sb = new StringBuilder();
+
+ if (defaultFastViews.size() > 0) {
+ sb.append(DEFAULT_FASTVIEW_STACK).append(' ');
+ sb.append(SideValue.BOTTOM_VALUE).append(' ').append(bottomCounter++);
+ sb.append('#');
+ }
+
+ if (fastViewBars.size() > 0) {
+ for (InfoReader folder : perspReader.getInfos()) {
+ String folderId = folder.getId();
+ if (!fastViewBars.containsKey(folderId)) {
+ continue;
+ }
+
+ sb.append(folderId).append(' ');
+
+ Integer side = fastViewBars.get(folderId);
+ if (side == null) {
+ side = SWT.LEFT;
+ }
+
+ switch (side) {
+ case SWT.TOP:
+ sb.append(SideValue.TOP_VALUE).append(' ').append(topCounter++);
+ break;
+ case SWT.BOTTOM:
+ sb.append(SideValue.BOTTOM_VALUE).append(' ').append(bottomCounter++);
+ break;
+ case SWT.RIGHT:
+ sb.append(SideValue.RIGHT_VALUE).append(' ').append(rightCounter++);
+ break;
+ default:
+ sb.append(SideValue.LEFT_VALUE).append(' ').append(leftCounter++);
+ break;
+ }
+
+ sb.append('#');
+ }
+ }
+ perspective.getPersistedState().put("trims", sb.toString()); //$NON-NLS-1$
+ }
+
+ private void hideEmptyStacks() {
+ for (MPartStack stack : modelService.findElements(perspective, null, MPartStack.class, null)) {
+ if (ID_EDITOR_AREA.equals(stack.getElementId()) || ID_EDITOR_AREA.equals(stack.getParent().getElementId())) {
+ continue;
+ }
+ if (!hasRenderableContent(stack)) {
+ stack.setToBeRendered(false);
+ }
+ }
+ }
+
+ private void setZoomState() {
+ List<MPartStack> stacks = modelService.findElements(perspective, null, MPartStack.class, null);
+ boolean isAnythingMaximized = isMaximized(editorAreaPlaceholder) || isAnyMaximized(stacks);
+ if (isAnythingMaximized) {
+ markMinimizedByZoom(editorAreaPlaceholder);
+ for (MPartStack stack : stacks) {
+ markMinimizedByZoom(stack);
+ }
+ }
+ }
+
+ private void markMinimizedByZoom(MUIElement element) {
+ List<String> tags = element.getTags();
+ if (tags.contains(IPresentationEngine.MINIMIZED)) {
+ tags.add(IPresentationEngine.MINIMIZED_BY_ZOOM);
+ }
+ }
+
+ private boolean isAnyMaximized(List<MPartStack> stacks) {
+ for (MPartStack stack : stacks) {
+ if (isMaximized(stack)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isMaximized(MUIElement element) {
+ return element.getTags().contains(IPresentationEngine.MAXIMIZED);
+ }
+
+ private void hideUrenderableSashes() {
+ for (MPartSashContainer sash : modelService.findElements(perspective, null, MPartSashContainer.class, null)) {
+ hideUnrenderableSash(sash);
+ }
+ }
+
+ private void hideInvisibleSashes() {
+ for (MPartSashContainer sash : modelService.findElements(perspective, null, MPartSashContainer.class, null)) {
+ hideInvisibleSash(sash);
+ }
+ }
+
+ private void hideInvisibleSash(MElementContainer<?> container) {
+ if ((container instanceof MPartSashContainer) && container != perspective) {
+ if (!hasVisibleContent((MPartSashContainer) container)) {
+ container.setVisible(false);
+ hideInvisibleSash(container.getParent());
+ }
+ }
+ }
+
+ private boolean hasVisibleContent(MPartSashContainer sash) {
+ for (MPartSashContainerElement child : sash.getChildren()) {
+ if (child.isVisible()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void hideUnrenderableSash(MElementContainer<?> container) {
+ if ((container instanceof MPartSashContainer) && container != perspective) {
+ if (modelService.countRenderableChildren(container) == 0) {
+ container.setToBeRendered(false);
+ hideUnrenderableSash(container.getParent());
+ }
+ }
+ }
+
+ private boolean hasRenderableContent(MPartStack stack) {
+ for (MStackElement child : stack.getChildren()) {
+ if (child.isVisible() && child.isToBeRendered()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void correctSelectedElements() {
+ List<MPartSashContainerElement> perspChildren = perspective.getChildren();
+ if (perspective.getSelectedElement() == null && !perspChildren.isEmpty()) {
+ for (MPartSashContainerElement child : perspChildren) {
+ if (child.isToBeRendered()) {
+ perspective.setSelectedElement(child);
+ break;
+ }
+ }
+ }
+
+ for (MPartSashContainerElement child : perspChildren) {
+ correctSelectedElements(child);
+ }
+ }
+
+ private void correctSelectedElements(MUIElement element) {
+ if (!(element instanceof MPartSashContainer || element instanceof MPartStack)) {
+ return;
+ }
+ @SuppressWarnings("unchecked")
+ MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) element;
+ List<MUIElement> children = container.getChildren();
+ if (container.getSelectedElement() == null && !children.isEmpty()) {
+ MUIElement firstRenderableElement = getFirstRenderableElement(children);
+ if (firstRenderableElement != null) {
+ container.setSelectedElement(firstRenderableElement);
+ }
+ }
+ for (MUIElement child : children) {
+ correctSelectedElements(child);
+ }
+ }
+
+ private MUIElement getFirstRenderableElement(List<MUIElement> elements) {
+ for (MUIElement element : elements) {
+ if (element.isToBeRendered()) {
+ return element;
+ }
+ }
+ return null;
+ }
+
+ private void addToPerspective(MPartSashContainerElement element, InfoReader info) {
+ if (info.isRelativelyPositioned()) {
+ insert(element, info);
+ } else {
+ perspective.getChildren().add(element);
+ }
+ }
+
+ private void addEditorArea(InfoReader info) {
+ editorAreaPlaceholder = modelService.createModelElement(MPlaceholder.class);
+ editorAreaPlaceholder.setElementId(ID_EDITOR_AREA);
+ editorAreaPlaceholder.setToBeRendered(perspReader.isEditorAreaVisible());
+ setPartState(editorAreaPlaceholder, perspReader.getEditorAreaState());
+ addToPerspective(editorAreaPlaceholder, info);
+ }
+
+ private MPartStack addPartStack(InfoReader info) {
+ MPartStack stack = createPartStack(info);
+ if (info.isRelativelyPositioned()) {
+ String refElementId = info.getRelative();
+ MUIElement refElement = modelService.find(refElementId, perspective);
+ MElementContainer<?> parent = refElement.getParent();
+ // don't put a stack in another stack
+ if (parent instanceof MPartStack) {
+ refElement = parent;
+ }
+
+ insert(stack, refElement, info);
+ } else {
+ perspective.getChildren().add(stack);
+ }
+ setPartState(stack, info.getState());
+ return stack;
+ }
+
+ private MPartStack addDefaultFastViewStack() {
+ MPartStack stack = null;
+ List<String> views = perspReader.getDefaultFastViewBarViewIds();
+ if (views.size() > 0) {
+ stack = layoutUtils.createStack(DEFAULT_FASTVIEW_STACK, true);
+ perspective.getChildren().add(stack);
+ setPartState(stack, org.eclipse.ui.internal.e4.migration.InfoReader.PartState.MINIMIZED);
+
+ for (String view : views) {
+ addPlaceholderToDefaultFastViewStack(stack, view, null);
+ }
+ }
+ return stack;
+ }
+
+ private void setPartState(MUIElement element, PartState state) {
+ List<String> tags = element.getTags();
+ switch (state) {
+ case MINIMIZED:
+ tags.add(IPresentationEngine.MINIMIZED);
+ element.setVisible(false);
+ break;
+ case MAXIMIZED:
+ tags.add(IPresentationEngine.MAXIMIZED);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void insert(MUIElement element, MUIElement refElement, InfoReader info) {
+ layoutUtils.insert(element, refElement, layoutUtils.plRelToSwt(info.getRelationship()), info.getRatio());
+ }
+
+ private void insert(MUIElement element, InfoReader info) {
+ insert(element, modelService.find(info.getRelative(), perspective), info);
+ }
+
+ private MPartStack createPartStack(InfoReader info) {
+ String stackId = info.getId();
+ if (stackId != null) {
+ if (stackId.equals(StickyViewDescriptor.STICKY_FOLDER_RIGHT)) {
+ stackId = "legacyStickyFolderRight"; //$NON-NLS-1$
+ }
+ }
+ return layoutUtils.createStack(stackId, true);
+ }
+
+ private void populatePartStack(MPartStack stack, InfoReader info) {
+ for (PageReader page : info.getPages()) {
+ addPlaceholderToStack(stack, page.getId(), page.getLabel());
+ }
+ MStackElement selectedElement = (MStackElement) modelService.find(info.getActivePageId(), stack);
+ if (selectedElement != null) {
+ selectedElement.setToBeRendered(true);
+ selectedElement.setVisible(true);
+ }
+ stack.setSelectedElement(selectedElement);
+
+ // restore order of views in the stacks
+ List<MStackElement> renderedViews = getRenderedViews(stack);
+ if (renderedViews.size() < 2) {
+ return;
+ }
+
+ int[] partOrder = info.getPartOrder();
+ List<MStackElement> stackChildren = stack.getChildren();
+ // unexpected situation - don't order
+ if (partOrder == null || partOrder.length != renderedViews.size()) {
+ return;
+ }
+ List<MStackElement> originalOrder = new ArrayList<MStackElement>(renderedViews);
+ stackChildren.clear();
+ for (int i = 0; i < partOrder.length; i++) {
+ stackChildren.add(originalOrder.get(partOrder[i]));
+ }
+ originalOrder.removeAll(stackChildren);
+ stackChildren.addAll(originalOrder);
+ }
+
+ private List<MStackElement> getRenderedViews(MPartStack stack) {
+ List<MStackElement> renderedViews = new ArrayList<MStackElement>();
+ for (MStackElement element : stack.getChildren()) {
+ if (element.isToBeRendered()) {
+ renderedViews.add(element);
+ }
+ }
+ return renderedViews;
+ }
+
+ private void populatePartStack(MPartStack stack, DetachedWindowReader info) {
+ for (PageReader page : info.getPages()) {
+ addPlaceholderToStack(stack, page.getId(), page.getLabel());
+ }
+ stack.setSelectedElement((MStackElement) modelService.find(info.getActivePageId(), stack));
+ }
+
+ private void addPlaceholderToStack(MPartStack stack, String partId, String label) {
+ if (partId == null || isDefaultFastView(partId)) {
+ return;
+ }
+ MPlaceholder placeholder = createPlaceHolder(partId, label);
+ if (!isToBeRendered(placeholder)) {
+ placeholder.setToBeRendered(false);
+ }
+ addLayoutTagsToPlaceholder(placeholder, partId);
+ stack.getChildren().add(placeholder);
+ viewPlaceholders.put(partId, placeholder);
+ }
+
+ private void addPlaceholderToDefaultFastViewStack(MPartStack stack, String partId, String label) {
+ MPlaceholder placeholder = createPlaceHolder(partId, label);
+ if (!isDefaultFastView(placeholder)) {
+ placeholder.setToBeRendered(false);
+ }
+ addLayoutTagsToPlaceholder(placeholder, partId);
+ stack.getChildren().add(placeholder);
+ if (viewPlaceholders.get(partId) != null) {
+ viewPlaceholders.put(partId, placeholder);
+ }
+ }
+
+ private void addLayoutTagsToPlaceholder(MPlaceholder placeholder, String partId) {
+ ViewLayoutReader viewLayout = getViewLayout(partId);
+ if (viewLayout == null) {
+ return;
+ }
+ List<String> tags = placeholder.getTags();
+ if (!viewLayout.isCloseable()) {
+ tags.add(IPresentationEngine.NO_CLOSE);
+ }
+ if (viewLayout.isStandalone()) {
+ tags.add(IPresentationEngine.STANDALONE);
+ }
+ }
+
+ private boolean isToBeRendered(MPlaceholder placeholder) {
+ if (renderedViews == null) {
+ renderedViews = perspReader.getRenderedViewIds();
+ }
+ return renderedViews.contains(placeholder.getElementId());
+ }
+
+ private boolean isDefaultFastView(MPlaceholder placeholder) {
+ if (defaultFastViews == null) {
+ defaultFastViews = perspReader.getDefaultFastViewBarViewIds();
+ }
+ return defaultFastViews.contains(placeholder.getElementId());
+ }
+
+ private boolean isDefaultFastView(String placeholderId) {
+ if (defaultFastViews == null) {
+ defaultFastViews = perspReader.getDefaultFastViewBarViewIds();
+ }
+ return defaultFastViews.contains(placeholderId);
+ }
+
+ private void addPerspectiveShortcutTags() {
+ for (String shortcutId : perspReader.getPerspectiveShortcutIds()) {
+ tags.add(ModeledPageLayout.PERSP_SHORTCUT_TAG + shortcutId);
+ }
+ }
+
+ private void addActionSetTags() {
+ for (String actionSetId : perspReader.getActionSetIds()) {
+ tags.add(ModeledPageLayout.ACTION_SET_TAG + actionSetId);
+ }
+ }
+
+ private void addShowInTags() {
+ String origId = null;
+ if (perspReader.isCustom()) {
+ origId = perspReader.getBasicPerspectiveId();
+ } else {
+ origId = perspReader.getId();
+ }
+ ArrayList<String> list = getShowInPartFromRegistry(origId);
+ if (list != null) {
+ for (String showIn : list) {
+ tags.add(ModeledPageLayout.SHOW_IN_PART_TAG + showIn);
+ }
+ }
+ return;
+ }
+
+ public static ArrayList<String> getShowInPartFromRegistry(String targetId) {
+ ArrayList<String> list = new ArrayList<String>();
+ IExtension[] extensions = getPerspectiveExtensions();
+ if (extensions != null) {
+ for (int i = 0; i < extensions.length; i++) {
+ list.addAll(getExtensionShowInPartFromRegistry(extensions[i], targetId));
+ }
+ }
+ return list;
+ }
+
+ private static IExtension[] getPerspectiveExtensions() {
+ IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(PlatformUI.PLUGIN_ID,
+ IWorkbenchRegistryConstants.PL_PERSPECTIVE_EXTENSIONS);
+ if (point == null) {
+ return null;
+ }
+ IExtension[] extensions = point.getExtensions();
+ extensions = RegistryReader.orderExtensions(extensions);
+ return extensions;
+ }
+
+ private static ArrayList<String> getExtensionShowInPartFromRegistry(IExtension extension, String targetId) {
+ ArrayList<String> list = new ArrayList<String>();
+ IConfigurationElement[] configElements = extension.getConfigurationElements();
+ for (int j = 0; j < configElements.length; j++) {
+ String type = configElements[j].getName();
+ if (type.equals(IWorkbenchRegistryConstants.TAG_PERSPECTIVE_EXTENSION)) {
+ String id = configElements[j].getAttribute(IWorkbenchRegistryConstants.ATT_TARGET_ID);
+ if (targetId.equals(id) || "*".equals(id)) { //$NON-NLS-1$
+ list.addAll(getConfigElementShowInPartsFromRegistry(configElements[j]));
+ }
+ }
+ }
+ return list;
+ }
+
+ private static ArrayList<String> getConfigElementShowInPartsFromRegistry(IConfigurationElement configElement) {
+ ArrayList<String> list = new ArrayList<String>();
+ String tag = IWorkbenchRegistryConstants.TAG_SHOW_IN_PART;
+ IConfigurationElement[] children = configElement.getChildren();
+ for (int nX = 0; nX < children.length; nX++) {
+ IConfigurationElement child = children[nX];
+ String ctype = child.getName();
+ if (tag.equals(ctype)) {
+ String tid = child.getAttribute(IWorkbenchRegistryConstants.ATT_ID);
+ if (tid != null) {
+ list.add(tid);
+ }
+ }
+ }
+ return list;
+ }
+
+ private void addNewWizardTags() {
+ for (String actionId : perspReader.getNewWizardActionIds()) {
+ tags.add(ModeledPageLayout.NEW_WIZARD_TAG + actionId);
+ }
+ }
+
+ private void addShowViewTags() {
+ for (String actionId : perspReader.getShowViewActionIds()) {
+ tags.add(ModeledPageLayout.SHOW_VIEW_TAG + actionId);
+ }
+ }
+
+ private void addHiddenItems() {
+ String comma = ","; //$NON-NLS-1$
+ StringBuilder persistedValue = new StringBuilder();
+ for (String elementId : perspReader.getHiddenMenuItemIds()) {
+ persistedValue.append(ModeledPageLayout.HIDDEN_MENU_PREFIX);
+ persistedValue.append(elementId).append(comma);
+ }
+ for (String elementId : perspReader.getHiddenToolbarItemIds()) {
+ persistedValue.append(ModeledPageLayout.HIDDEN_TOOLBAR_PREFIX);
+ persistedValue.append(elementId).append(comma);
+ }
+ perspective.getPersistedState().put(ModeledPageLayout.HIDDEN_ITEMS_KEY, persistedValue.toString());
+ }
+
+ private ViewLayoutReader getViewLayout(String viewId) {
+ if (viewLayouts == null) {
+ viewLayouts = perspReader.getViewLayouts();
+ }
+ return viewLayouts.get(viewId);
+ }
+
+ Collection<MPlaceholder> getPlaceholders() {
+ return viewPlaceholders.values();
+ }
+
+ MPlaceholder getEditorAreaPlaceholder() {
+ return editorAreaPlaceholder;
+ }
+
+ MPlaceholder createPlaceHolder(String str, String label) {
+ MPlaceholder placeholder = null;
+ placeholder = modelService.createModelElement(MPlaceholder.class);
+ placeholder.setElementId(str);
+ if (modelService.getPartDescriptor(str) == null) {
+ placeholder.getTransientData().put(IWorkbenchConstants.TAG_LABEL, label);
+ }
+ return placeholder;
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/PerspectiveReader.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/PerspectiveReader.java
new file mode 100644
index 00000000000..0e49b7d692f
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/e4/migration/PerspectiveReader.java
@@ -0,0 +1,336 @@
+/*******************************************************************************
+ * Copyright (c) 2015 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.ui.internal.e4.migration;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.internal.IWorkbenchConstants;
+import org.eclipse.ui.internal.e4.migration.InfoReader.PageReader;
+import org.eclipse.ui.internal.e4.migration.InfoReader.PartState;
+
+public class PerspectiveReader extends MementoReader {
+
+ private DescriptorReader descriptor;
+
+ public PerspectiveReader(IMemento memento) {
+ super(memento);
+ }
+
+ String getId() {
+ return getDescriptor().getId();
+ }
+
+ String getLabel() {
+ return getDescriptor().getLabel();
+ }
+
+ private DescriptorReader getDescriptor() {
+ if (descriptor == null) {
+ IMemento desriptorMem = getChild(IWorkbenchConstants.TAG_DESCRIPTOR);
+ if (desriptorMem == null) {
+ throw new NullPointerException("Perspective descriptor not found"); //$NON-NLS-1$
+ }
+ descriptor = new DescriptorReader(desriptorMem);
+ }
+ return descriptor;
+ }
+
+ List<InfoReader> getInfos() {
+ IMemento[] infoMems = getInfoMems();
+ List<InfoReader> infos = new ArrayList<InfoReader>(infoMems.length);
+ for (IMemento infoMem : infoMems) {
+ infos.add(new InfoReader(infoMem));
+ }
+ return infos;
+ }
+
+ private IMemento[] getInfoMems() {
+ IMemento[] infoMems = null;
+ IMemento layout = getLayout();
+ if (layout != null) {
+ IMemento mainWindow = layout.getChild(IWorkbenchConstants.TAG_MAIN_WINDOW);
+ if (mainWindow != null) {
+ infoMems = mainWindow.getChildren(IWorkbenchConstants.TAG_INFO);
+ }
+ }
+ if (infoMems == null) {
+ infoMems = new IMemento[0];
+ }
+ return infoMems;
+ }
+
+ Map<String, ViewLayoutReader> getViewLayouts() {
+ IMemento[] viewLayoutMems = getChildren(IWorkbenchConstants.TAG_VIEW_LAYOUT_REC);
+ Map<String, ViewLayoutReader> viewLayouts = new HashMap<String, ViewLayoutReader>(
+ viewLayoutMems.length);
+ for (IMemento memento : viewLayoutMems) {
+ ViewLayoutReader viewLayout = new ViewLayoutReader(memento);
+ viewLayouts.put(viewLayout.getViewId(), viewLayout);
+ }
+ return viewLayouts;
+ }
+
+ private IMemento getLayout() {
+ return getChild(IWorkbenchConstants.TAG_LAYOUT);
+ }
+
+ List<String> getPerspectiveShortcutIds() {
+ return getChildrenIds(IWorkbenchConstants.TAG_PERSPECTIVE_ACTION);
+ }
+
+ List<String> getActionSetIds() {
+ return getChildrenIds(IWorkbenchConstants.TAG_ALWAYS_ON_ACTION_SET);
+ }
+
+ List<String> getShowViewActionIds() {
+ return getChildrenIds(IWorkbenchConstants.TAG_SHOW_VIEW_ACTION);
+ }
+
+ List<String> getNewWizardActionIds() {
+ return getChildrenIds(IWorkbenchConstants.TAG_NEW_WIZARD_ACTION);
+ }
+
+ List<String> getRenderedViewIds() {
+ List<String> viewIds = getChildrenIds(IWorkbenchConstants.TAG_VIEW);
+ viewIds.addAll(getFastViewIds());
+ return viewIds;
+ }
+
+ /**
+ * @return map of fast view bar's ID and side
+ */
+ Map<String, Integer> getFastViewBars() {
+ Map<String, Integer> bars = new HashMap<String, Integer>();
+ for (IMemento bar : getFastViewBarMems()) {
+ bars.put(bar.getString(IWorkbenchConstants.TAG_ID),
+ bar.getInteger(IWorkbenchConstants.TAG_FAST_VIEW_SIDE));
+ }
+ return bars;
+ }
+
+ private List<String> getFastViewIds() {
+ List<String> fastViewIds = new ArrayList<String>();
+
+ IMemento fastViews = getChild(IWorkbenchConstants.TAG_FAST_VIEWS);
+ if (fastViews != null) {
+ for (IMemento view : fastViews.getChildren(IWorkbenchConstants.TAG_VIEW)) {
+ fastViewIds.add(view.getString(IWorkbenchConstants.TAG_ID));
+ }
+ }
+
+ IMemento[] fastViewBarArr = getFastViewBarMems();
+ for (IMemento fastViewBar : fastViewBarArr) {
+ IMemento fastViewsInBar = fastViewBar.getChild(IWorkbenchConstants.TAG_FAST_VIEWS);
+ if (fastViewsInBar != null) {
+ for (IMemento view : fastViewsInBar.getChildren(IWorkbenchConstants.TAG_VIEW)) {
+ fastViewIds.add(view.getString(IWorkbenchConstants.TAG_ID));
+ }
+ }
+ }
+ return fastViewIds;
+ }
+
+ List<String> getDefaultFastViewBarViewIds() {
+ List<String> fastViewIds = new ArrayList<String>();
+ IMemento fastViews = getChild(IWorkbenchConstants.TAG_FAST_VIEWS);
+ if (fastViews != null) {
+ for (IMemento view : fastViews.getChildren(IWorkbenchConstants.TAG_VIEW)) {
+ fastViewIds.add(view.getString(IWorkbenchConstants.TAG_ID));
+ }
+ }
+
+ return fastViewIds;
+ }
+
+ private IMemento[] getFastViewBarMems() {
+ IMemento[] emptyArr = new IMemento[0];
+ IMemento fastViewBars = getChild(IWorkbenchConstants.TAG_FAST_VIEW_BARS);
+ if (fastViewBars == null) {
+ return emptyArr;
+ }
+ IMemento[] fastViewBarArr = fastViewBars.getChildren(IWorkbenchConstants.TAG_FAST_VIEW_BAR);
+ return fastViewBarArr == null ? emptyArr : fastViewBarArr;
+ }
+
+ List<String> getHiddenMenuItemIds() {
+ return getChildrenIds(IWorkbenchConstants.TAG_HIDE_MENU);
+ }
+
+ List<String> getHiddenToolbarItemIds() {
+ return getChildrenIds(IWorkbenchConstants.TAG_HIDE_TOOLBAR);
+ }
+
+ private List<String> getChildrenIds(String tag) {
+ IMemento[] idMemArr = getChildren(tag);
+ List<String> idList = new ArrayList<String>(idMemArr.length);
+ for (IMemento idMem : idMemArr) {
+ idList.add(idMem.getString(IWorkbenchConstants.TAG_ID));
+ }
+ return idList;
+ }
+
+ List<DetachedWindowReader> getDetachedWindows() {
+ List<DetachedWindowReader> readers = new ArrayList<DetachedWindowReader>();
+ IMemento layout = getLayout();
+ if (layout != null) {
+ IMemento[] mems = layout.getChildren(IWorkbenchConstants.TAG_DETACHED_WINDOW);
+ for (IMemento mem : mems) {
+ readers.add(new DetachedWindowReader(mem));
+ }
+ }
+ return readers;
+ }
+
+ boolean isCustom() {
+ return getDescriptor().isCustom();
+ }
+
+ String getBasicPerspectiveId() {
+ return getDescriptor().getBasicPerspectiveId();
+ }
+
+ String getOriginalId() {
+ return getDescriptor().getOriginalId();
+ }
+
+ boolean isEditorAreaVisible() {
+ return Integer.valueOf(1).equals(getInteger(IWorkbenchConstants.TAG_AREA_VISIBLE));
+ }
+
+ PartState getEditorAreaState() {
+ PartState state = PartState.RESTORED;
+ int value = getInteger(IWorkbenchConstants.TAG_AREA_TRIM_STATE);
+ switch (value) {
+ case 0:
+ case 4: // minimized by zoom
+ state = PartState.MINIMIZED;
+ break;
+ case 1:
+ state = PartState.MAXIMIZED;
+ break;
+ }
+ return state;
+ }
+
+ static class DetachedWindowReader extends MementoReader {
+
+ private DetachedWindowReader(IMemento memento) {
+ super(memento);
+ }
+
+ Rectangle getBounds() {
+ Rectangle windowBounds = new Rectangle(0, 0, 0, 0);
+ Integer bigInt = getInteger(IWorkbenchConstants.TAG_X);
+ windowBounds.x = bigInt == null ? 0 : bigInt.intValue();
+ bigInt = getInteger(IWorkbenchConstants.TAG_Y);
+ windowBounds.y = bigInt == null ? 0 : bigInt.intValue();
+ bigInt = getInteger(IWorkbenchConstants.TAG_WIDTH);
+ windowBounds.width = bigInt == null ? 0 : bigInt.intValue();
+ bigInt = getInteger(IWorkbenchConstants.TAG_HEIGHT);
+ windowBounds.height = bigInt == null ? 0 : bigInt.intValue();
+ return windowBounds;
+ }
+
+ String getActivePageId() {
+ String activePageId = null;
+ IMemento folder = getFolder();
+ if (folder != null) {
+ activePageId = folder.getString(IWorkbenchConstants.TAG_ACTIVE_PAGE_ID);
+ }
+ return activePageId;
+ }
+
+ List<PageReader> getPages() {
+ IMemento folder = getFolder();
+ List<PageReader> pages = new ArrayList<PageReader>();
+ if (folder != null) {
+ IMemento[] pageMems = folder.getChildren(IWorkbenchConstants.TAG_PAGE);
+ for (IMemento pageMem : pageMems) {
+ pages.add(new PageReader(pageMem));
+ }
+ }
+ return pages;
+ }
+
+ private IMemento getFolder() {
+ return getChild(IWorkbenchConstants.TAG_FOLDER);
+ }
+
+ }
+
+ private static class DescriptorReader extends MementoReader {
+
+ private static final String TAG_DESCRIPTOR = IWorkbenchConstants.TAG_DESCRIPTOR;
+
+ DescriptorReader(IMemento memento) {
+ super(memento);
+ }
+
+ String getId() {
+ String id = getOriginalId();
+ if (isCustom()) {
+ id = getBasicPerspectiveId() + "." + id; //$NON-NLS-1$
+ }
+ return id;
+ }
+
+ String getOriginalId() {
+ String id = getString(IWorkbenchConstants.TAG_ID);
+ if (id == null) {
+ throw new NullPointerException("Perspective ID not found"); //$NON-NLS-1$
+ }
+ return id;
+ }
+
+ boolean isCustom() {
+ return contains(TAG_DESCRIPTOR);
+ }
+
+ String getBasicPerspectiveId() {
+ String id = getString(TAG_DESCRIPTOR);
+ if (id == null) {
+ throw new NullPointerException("Basic perspective ID not found"); //$NON-NLS-1$
+ }
+ return id;
+ }
+
+ String getLabel() {
+ return getString(IWorkbenchConstants.TAG_LABEL);
+ }
+
+ }
+
+ static class ViewLayoutReader extends MementoReader {
+
+ private ViewLayoutReader(IMemento memento) {
+ super(memento);
+ }
+
+ String getViewId() {
+ return getString(IWorkbenchConstants.TAG_ID);
+ }
+
+ boolean isCloseable() {
+ return getBoolean(IWorkbenchConstants.TAG_CLOSEABLE, true);
+ }
+
+ boolean isStandalone() {
+ return getBoolean(IWorkbenchConstants.TAG_STANDALONE);
+ }
+
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/registry/ImportExportPespectiveHandler.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/registry/ImportExportPespectiveHandler.java
new file mode 100644
index 00000000000..72fe8103b87
--- /dev/null
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/registry/ImportExportPespectiveHandler.java
@@ -0,0 +1,362 @@
+/*******************************************************************************
+ * Copyright (c) 2015 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.ui.internal.registry;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.di.extensions.Preference;
+import org.eclipse.e4.core.services.events.IEventBroker;
+import org.eclipse.e4.core.services.log.Logger;
+import org.eclipse.e4.ui.internal.workbench.E4XMIResourceFactory;
+import org.eclipse.e4.ui.model.application.MAddon;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.ui.IPerspectiveDescriptor;
+import org.eclipse.ui.WorkbenchException;
+import org.eclipse.ui.XMLMemento;
+import org.eclipse.ui.internal.e4.compatibility.ModeledPageLayout;
+import org.eclipse.ui.internal.e4.migration.PerspectiveBuilder;
+import org.eclipse.ui.internal.e4.migration.PerspectiveReader;
+import org.eclipse.ui.internal.wizards.preferences.PreferencesExportWizard;
+import org.eclipse.ui.internal.wizards.preferences.PreferencesImportWizard;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+@SuppressWarnings("restriction")
+public class ImportExportPespectiveHandler {
+
+ private static final String PERSPECTIVE_SUFFIX_4X = "_e4persp"; //$NON-NLS-1$
+
+ private static final String PERSPECTIVE_SUFFIX_3X = "_persp"; //$NON-NLS-1$
+
+ private static final String ASCII_ENCODING = "ASCII"; //$NON-NLS-1$
+
+ private static final String TRIMS_KEY = "trims"; //$NON-NLS-1$
+
+ @Inject
+ private EModelService modelService;
+
+ @Inject
+ private MApplication application;
+
+ @Inject
+ private IEventBroker eventBroker;
+
+ @Inject
+ private Logger logger;
+
+ @Inject @Preference(nodePath="org.eclipse.ui.workbench")
+ private IEclipsePreferences preferences;
+
+ @Inject
+ private IEclipseContext context;
+
+ @Inject
+ private PerspectiveRegistry perspectiveRegistry;
+
+ private EventHandler importPreferencesEnd;
+ private EventHandler exportPreferencesBegin;
+ private EventHandler exportPreferencesEnd;
+ private IPreferenceChangeListener preferenceListener;
+ private boolean ignoreEvents;
+
+ private List<MPerspective> exportedPersps = new ArrayList<MPerspective>();
+ private List<String> importedPersps = new ArrayList<String>();
+ private Map<String, String> minMaxPersistedState;
+
+ private Boolean impExpEnabled;
+
+ @PostConstruct
+ private void init() {
+ if (!isImpExpEnabled()) {
+ return;
+ }
+
+ initializeEventHandlers();
+ preferences.addPreferenceChangeListener(preferenceListener);
+ eventBroker.subscribe(PreferencesExportWizard.EVENT_EXPORT_BEGIN, exportPreferencesBegin);
+ eventBroker.subscribe(PreferencesExportWizard.EVENT_EXPORT_END, exportPreferencesEnd);
+ eventBroker.subscribe(PreferencesImportWizard.EVENT_IMPORT_END, importPreferencesEnd);
+ }
+
+ @PreDestroy
+ private void dispose() {
+ if (!isImpExpEnabled()) {
+ return;
+ }
+
+ preferences.removePreferenceChangeListener(preferenceListener);
+ eventBroker.unsubscribe(exportPreferencesBegin);
+ eventBroker.unsubscribe(exportPreferencesEnd);
+ eventBroker.unsubscribe(importPreferencesEnd);
+ }
+
+ private void importPerspective4x(PreferenceChangeEvent event) {
+ importedPersps.add(event.getKey());
+ MPerspective perspective = null;
+ try {
+ perspective = perspFromString((String) event.getNewValue());
+ addShowInTags(perspective);
+ } catch (IOException e) {
+ logError(event, e);
+ }
+ addPerspectiveToWorkbench(perspective);
+ }
+
+ private void addShowInTags(MPerspective perspective) {
+ if (perspective != null) {
+ String targetId = getOriginalId(perspective.getElementId());
+ ArrayList<String> showInTags = PerspectiveBuilder.getShowInPartFromRegistry(targetId);
+ if (showInTags != null) {
+ List<String> newTags = new ArrayList<String>();
+ for (String showIn : showInTags) {
+ newTags.add(ModeledPageLayout.SHOW_IN_PART_TAG + showIn);
+ }
+ perspective.getTags().addAll(newTags);
+ }
+ }
+ }
+
+ private String getOriginalId(String id) {
+ int index = id.lastIndexOf('.');
+ if (index == -1)
+ return id;
+ return id.substring(0, index);
+ }
+
+ private void importPerspective3x(PreferenceChangeEvent event) {
+ importedPersps.add(event.getKey());
+ StringReader reader = new StringReader((String) event.getNewValue());
+ MPerspective perspective = null;
+ IEclipseContext childContext = context.createChild();
+ try {
+ childContext.set(PerspectiveReader.class, new PerspectiveReader(XMLMemento.createReadRoot(reader)));
+ perspective = ContextInjectionFactory.make(PerspectiveBuilder.class, childContext).createPerspective();
+ } catch (WorkbenchException e) {
+ logError(event, e);
+ } finally {
+ reader.close();
+ childContext.dispose();
+ }
+ addPerspectiveToWorkbench(perspective);
+ }
+
+ private void addPerspectiveToWorkbench(MPerspective perspective) {
+ if (perspective == null) {
+ return;
+ }
+
+ IPerspectiveDescriptor perspToOverwrite = perspectiveRegistry.findPerspectiveWithLabel(perspective.getLabel());
+
+ // a new perspective
+ if (perspToOverwrite == null) {
+ perspectiveRegistry.addPerspective(perspective);
+ importToolbarsLocation(perspective);
+ return;
+ }
+
+ String perspToOverwriteId = perspToOverwrite.getId();
+ // a perspective with the same label exists, but has different ID
+ if (!perspective.getElementId().equals(perspToOverwriteId)) {
+ perspective.setElementId(perspToOverwriteId);
+ }
+ perspectiveRegistry.deletePerspective(perspToOverwrite);
+ perspectiveRegistry.addPerspective(perspective);
+ importToolbarsLocation(perspective);
+ }
+
+ private void logError(PreferenceChangeEvent event, Exception e) {
+ logger.error(e, String.format("Cannot read perspective \"%s\" from preferences", event.getKey())); //$NON-NLS-1$
+ }
+
+ private void copyPerspToPreferences(MPerspective persp) throws IOException {
+ MPerspective perspClone = (MPerspective) modelService.cloneElement(persp, null);
+ exportToolbarsLocation(perspClone);
+ String perspAsString = perspToString(perspClone);
+ preferences.put(perspClone.getLabel() + PERSPECTIVE_SUFFIX_4X, perspAsString);
+ }
+
+ private void exportToolbarsLocation(MPerspective persp) {
+ Map<String, String> minMaxPersState = getMinMaxPersistedState();
+ if (minMaxPersState == null) {
+ return;
+ }
+ String trimsData = minMaxPersState.get(persp.getElementId());
+ persp.getPersistedState().put(TRIMS_KEY, trimsData);
+ }
+
+ private void importToolbarsLocation(MPerspective persp) {
+ String trimsData = persp.getPersistedState().get(TRIMS_KEY);
+ if (trimsData == null || trimsData.trim().isEmpty()) {
+ return;
+ }
+ persp.getPersistedState().remove(TRIMS_KEY);
+ Map<String, String> minMaxPersState = getMinMaxPersistedState();
+ if (minMaxPersState == null) {
+ return;
+ }
+ minMaxPersState.put(persp.getElementId(), trimsData);
+ }
+
+ private Map<String, String> getMinMaxPersistedState() {
+ if (minMaxPersistedState != null) {
+ return minMaxPersistedState;
+ }
+ for (MAddon addon : application.getAddons()) {
+ if ("MinMax Addon".equals(addon.getElementId())) { //$NON-NLS-1$
+ minMaxPersistedState = addon.getPersistedState();
+ break;
+ }
+ }
+ return minMaxPersistedState;
+ }
+
+ private String perspToString(MPerspective persp) throws IOException {
+ Resource resource = new E4XMIResourceFactory().createResource(null);
+ resource.getContents().add((EObject) persp);
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ try {
+ resource.save(output, null);
+ } finally {
+ try {
+ output.close();
+ } catch (IOException e) {
+ logger.error(e, "Cannot close output stream"); //$NON-NLS-1$
+ }
+ }
+ resource.getContents().clear();
+ return new String(output.toByteArray(), ASCII_ENCODING);
+ }
+
+ private MPerspective perspFromString(String perspAsString) throws IOException {
+ Resource resource = new E4XMIResourceFactory().createResource(null);
+ InputStream input = new ByteArrayInputStream(perspAsString.getBytes(ASCII_ENCODING));
+ try {
+ resource.load(input, null);
+ } finally {
+ try {
+ input.close();
+ } catch (IOException e) {
+ logger.error(e, "Cannot close input stream"); //$NON-NLS-1$
+ }
+ }
+ MPerspective perspective = (MPerspective) resource.getContents().get(0);
+ resource.getContents().clear();
+ return perspective;
+ }
+
+ private void copyPerspsToPreferences() {
+ for (MUIElement snippet : application.getSnippets()) {
+ if (snippet instanceof MPerspective) {
+ MPerspective persp = (MPerspective) snippet;
+ exportedPersps.add(persp);
+ }
+ }
+ ignoreEvents = true;
+ for (MPerspective persp : exportedPersps) {
+ try {
+ copyPerspToPreferences(persp);
+ } catch (IOException e) {
+ logger.error(e, String.format("Cannot save perspective \"%s\" to preferences", persp.getElementId())); //$NON-NLS-1$
+ }
+ }
+ ignoreEvents = false;
+ }
+
+ private void removeExportedPreferences() {
+ ignoreEvents = true;
+ for (MPerspective persp : exportedPersps) {
+ preferences.remove(persp.getLabel() + PERSPECTIVE_SUFFIX_4X);
+ }
+ ignoreEvents = false;
+ exportedPersps.clear();
+ }
+
+ private void removeImportedPreferences() {
+ ignoreEvents = true;
+ for (String key : importedPersps) {
+ preferences.remove(key);
+ }
+ ignoreEvents = false;
+ importedPersps.clear();
+
+ // remove unused preference imported from Eclipse 3.x
+ preferences.remove("perspectives"); //$NON-NLS-1$
+ }
+
+ private void initializeEventHandlers() {
+
+ importPreferencesEnd = new EventHandler() {
+ @Override
+ public void handleEvent(Event event) {
+ removeImportedPreferences();
+ }
+ };
+
+ exportPreferencesBegin = new EventHandler() {
+ @Override
+ public void handleEvent(Event event) {
+ copyPerspsToPreferences();
+ }
+ };
+
+ exportPreferencesEnd = new EventHandler() {
+ @Override
+ public void handleEvent(Event event) {
+ removeExportedPreferences();
+ }
+ };
+
+ preferenceListener = new IPreferenceChangeListener() {
+ @Override
+ public void preferenceChange(PreferenceChangeEvent event) {
+ if (ignoreEvents) {
+ return;
+ }
+
+ if (event.getKey().endsWith(PERSPECTIVE_SUFFIX_4X)) {
+ importPerspective4x(event);
+ } else if (event.getKey().endsWith(PERSPECTIVE_SUFFIX_3X)) {
+ importPerspective3x(event);
+ }
+ }
+ };
+
+ }
+
+ private boolean isImpExpEnabled() {
+ impExpEnabled = true;
+ // if (impExpEnabled == null) {
+ //impExpEnabled = Boolean.parseBoolean(System.getProperty("e4.impExpPerspectiveEnabled")); //$NON-NLS-1$
+ // }
+ // return impExpEnabled;
+ return impExpEnabled;
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/registry/PerspectiveRegistry.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/registry/PerspectiveRegistry.java
index 57bc3116b20..9372f3557a2 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/registry/PerspectiveRegistry.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/registry/PerspectiveRegistry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -24,6 +24,9 @@ import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
+import org.eclipse.e4.core.contexts.ContextInjectionFactory;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.core.services.log.Logger;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MSnippetContainer;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
@@ -52,6 +55,14 @@ public class PerspectiveRegistry implements IPerspectiveRegistry, IExtensionChan
@Inject
MApplication application;
+ @Inject
+ IEclipseContext context;
+
+ private IEclipseContext impExpHandlerContext;
+
+ @Inject
+ Logger logger;
+
private Map<String, PerspectiveDescriptor> descriptors = new HashMap<String, PerspectiveDescriptor>();
@PostConstruct
@@ -73,18 +84,45 @@ public class PerspectiveRegistry implements IPerspectiveRegistry, IExtensionChan
if (existingDescriptor == null) {
// A custom perspective with its own name.
- String label = perspective.getLabel();
- String originalId = getOriginalId(perspective.getElementId());
- PerspectiveDescriptor originalDescriptor = descriptors.get(originalId);
- PerspectiveDescriptor newDescriptor = new PerspectiveDescriptor(id, label,
- originalDescriptor);
- descriptors.put(id, newDescriptor);
+ createDescriptor(perspective);
} else {
// A custom perspecitve with a name of a pre-defined perspective
existingDescriptor.setHasCustomDefinition(true);
}
}
}
+
+ impExpHandlerContext = context.createChild();
+ impExpHandlerContext.set(PerspectiveRegistry.class, this);
+ ContextInjectionFactory.make(ImportExportPespectiveHandler.class, impExpHandlerContext);
+ }
+
+ public void addPerspective(MPerspective perspective) {
+ application.getSnippets().add(perspective);
+ createDescriptor(perspective);
+ }
+
+ private void createDescriptor(MPerspective perspective) {
+ String label = perspective.getLocalizedLabel();
+ String originalId = getOriginalId(perspective.getElementId());
+ PerspectiveDescriptor originalDescriptor = descriptors.get(originalId);
+ String id = perspective.getElementId();
+ PerspectiveDescriptor newDescriptor = new PerspectiveDescriptor(id, label, originalDescriptor);
+
+ /*
+ * if (perspective.getIconURI() != null) { try { ImageDescriptor img =
+ * ImageDescriptor.createFromURL(new
+ * URI(perspective.getIconURI()).toURL());
+ * newDescriptor.setImageDescriptor(img); } catch (MalformedURLException
+ * e) { logger.warn(e,
+ * MessageFormat.format("Error on applying configured perspective icon: {0}"
+ * , //$NON-NLS-1$ perspective.getIconURI())); } catch
+ * (URISyntaxException e) { logger.warn(e,
+ * MessageFormat.format("Error on applying configured perspective icon: {0}"
+ * , //$NON-NLS-1$ perspective.getIconURI())); } }
+ */
+
+ descriptors.put(id, newDescriptor);
}
/**
@@ -270,6 +308,9 @@ public class PerspectiveRegistry implements IPerspectiveRegistry, IExtensionChan
* Dispose the receiver.
*/
public void dispose() {
+ if (impExpHandlerContext != null) {
+ impExpHandlerContext.dispose();
+ }
PlatformUI.getWorkbench().getExtensionTracker().unregisterHandler(this);
// FIXME: what was this listener for?
// WorkbenchPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/wizards/preferences/PreferencesExportWizard.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/wizards/preferences/PreferencesExportWizard.java
index 46cd9f03f28..7e0a126ba01 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/wizards/preferences/PreferencesExportWizard.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/wizards/preferences/PreferencesExportWizard.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.ui.internal.wizards.preferences;
+import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
@@ -45,8 +46,16 @@ import org.eclipse.ui.internal.WorkbenchPlugin;
*/
public class PreferencesExportWizard extends Wizard implements IExportWizard {
+ private static final String EVENT_TOPIC_BASE = "org/eclipse/ui/internal/wizards/preferences/export/"; //$NON-NLS-1$
+
+ public static final String EVENT_EXPORT_BEGIN = EVENT_TOPIC_BASE + "begin"; //$NON-NLS-1$
+
+ public static final String EVENT_EXPORT_END = EVENT_TOPIC_BASE + "end"; //$NON-NLS-1$
+
private WizardPreferencesExportPage1 mainPage;
+ private IEventBroker eventBroker;
+
/**
* Creates a wizard for exporting workspace preferences to the local file system.
*/
@@ -75,6 +84,7 @@ public class PreferencesExportWizard extends Wizard implements IExportWizard {
*/
@Override
public void init(IWorkbench workbench, IStructuredSelection currentSelection) {
+ eventBroker = workbench.getService(IEventBroker.class);
setWindowTitle(PreferencesMessages.PreferencesExportWizard_export);
setDefaultPageImageDescriptor(WorkbenchImages
.getImageDescriptor(IWorkbenchGraphicConstants.IMG_WIZBAN_EXPORT_PREF_WIZ));
@@ -86,7 +96,16 @@ public class PreferencesExportWizard extends Wizard implements IExportWizard {
*/
@Override
public boolean performFinish() {
- return mainPage.finish();
+ sendEvent(EVENT_EXPORT_BEGIN);
+ boolean success = mainPage.finish();
+ sendEvent(EVENT_EXPORT_END);
+ return success;
+ }
+
+ private void sendEvent(String topic) {
+ if (eventBroker != null) {
+ eventBroker.send(topic, null);
+ }
}
diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/wizards/preferences/PreferencesImportWizard.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/wizards/preferences/PreferencesImportWizard.java
index 4a779377ae7..adcc5b0cd1f 100644
--- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/wizards/preferences/PreferencesImportWizard.java
+++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/wizards/preferences/PreferencesImportWizard.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.ui.internal.wizards.preferences;
+import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
@@ -46,8 +47,12 @@ import org.eclipse.ui.internal.WorkbenchPlugin;
*/
public class PreferencesImportWizard extends Wizard implements IImportWizard {
- private WizardPreferencesImportPage1 mainPage;
+ public static final String EVENT_IMPORT_END = "org/eclipse/ui/internal/wizards/preferences/import/end"; //$NON-NLS-1$
+
+ private WizardPreferencesImportPage1 mainPage;
+ private IEventBroker eventBroker;
+
/**
* Creates a wizard for importing resources into the workspace from
* the file system.
@@ -77,6 +82,7 @@ public class PreferencesImportWizard extends Wizard implements IImportWizard {
*/
@Override
public void init(IWorkbench workbench, IStructuredSelection currentSelection) {
+ eventBroker = workbench.getService(IEventBroker.class);
setWindowTitle(PreferencesMessages.PreferencesImportWizard_import);
setDefaultPageImageDescriptor(WorkbenchImages
.getImageDescriptor(IWorkbenchGraphicConstants.IMG_WIZBAN_IMPORT_PREF_WIZ));
@@ -88,6 +94,14 @@ public class PreferencesImportWizard extends Wizard implements IImportWizard {
*/
@Override
public boolean performFinish() {
- return mainPage.finish();
+ boolean success = mainPage.finish();
+ sendEvent(EVENT_IMPORT_END);
+ return success;
}
+
+ private void sendEvent(String topic) {
+ if (eventBroker != null) {
+ eventBroker.send(topic, null);
+ }
+ }
}
diff --git a/bundles/org.eclipse.ui.workbench/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.workbench/META-INF/MANIFEST.MF
index 21df995da0f..4524328c0b1 100644
--- a/bundles/org.eclipse.ui.workbench/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.ui.workbench/META-INF/MANIFEST.MF
@@ -107,7 +107,9 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.6.0,4.0.0)",
org.eclipse.e4.ui.css.core;bundle-version="0.9.0",
org.eclipse.e4.ui.workbench3;bundle-version="0.12.0";visibility:=reexport,
org.eclipse.e4.ui.workbench.addons.swt;bundle-version="0.10.0",
- org.eclipse.emf.ecore;bundle-version="2.7.0"
+ org.eclipse.emf.ecore;bundle-version="2.7.0",
+ org.eclipse.e4.core.di.extensions;bundle-version="0.12.0",
+ org.eclipse.emf.ecore.xmi;bundle-version="2.10.2"
Import-Package: com.ibm.icu.text,
com.ibm.icu.util,
javax.annotation;version="1.0.0",

Back to the top