| /******************************************************************************* |
| * Copyright (c) 2011, 2019 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| ******************************************************************************/ |
| |
| package org.eclipse.e4.ui.workbench.addons.splitteraddon; |
| |
| import java.util.List; |
| import javax.inject.Inject; |
| import org.eclipse.e4.core.di.annotations.Optional; |
| import org.eclipse.e4.ui.di.UIEventTopic; |
| 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.basic.MCompositePart; |
| import org.eclipse.e4.ui.model.application.ui.basic.MPart; |
| import org.eclipse.e4.ui.workbench.IPresentationEngine; |
| import org.eclipse.e4.ui.workbench.UIEvents; |
| import org.eclipse.e4.ui.workbench.UIEvents.EventTags; |
| import org.eclipse.e4.ui.workbench.modeling.EModelService; |
| import org.eclipse.e4.ui.workbench.modeling.EPartService; |
| import org.osgi.service.event.Event; |
| |
| /** |
| * Listens for the IPresentationEngine's SPLIT_HORIZONTAL and SPLIT_VERTICAL tags being applied to |
| * an MPart and takes the appropriate steps to split / unsplit the part |
| */ |
| public class SplitterAddon { |
| @Inject |
| EModelService ms; |
| |
| @Inject |
| EPartService ps; |
| |
| /** |
| * Handles changes in tags |
| * |
| * @param event |
| */ |
| @Inject |
| @Optional |
| private void subscribeTopicTagsChanged( |
| @UIEventTopic(UIEvents.ApplicationElement.TOPIC_TAGS) Event event) { |
| Object changedObj = event.getProperty(EventTags.ELEMENT); |
| |
| if (!(changedObj instanceof MPart)) { |
| return; |
| } |
| |
| MPart part = (MPart) changedObj; |
| |
| if (UIEvents.isADD(event)) { |
| if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE, |
| IPresentationEngine.SPLIT_HORIZONTAL)) { |
| splitPart(part, true); |
| } else if (UIEvents.contains(event, UIEvents.EventTags.NEW_VALUE, |
| IPresentationEngine.SPLIT_VERTICAL)) { |
| splitPart(part, false); |
| } |
| } else if (UIEvents.isREMOVE(event)) { |
| MCompositePart compPart = SplitterAddon.findContainingCompositePart(part); |
| if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE, |
| IPresentationEngine.SPLIT_HORIZONTAL)) { |
| unsplitPart(compPart); |
| } else if (UIEvents.contains(event, UIEvents.EventTags.OLD_VALUE, |
| IPresentationEngine.SPLIT_VERTICAL)) { |
| unsplitPart(compPart); |
| } |
| } |
| } |
| |
| /** |
| * Finds the CompositePart containing the given part (if any) |
| * |
| * @param part |
| * @return The MCompositePart or 'null' if none is found |
| */ |
| public static MCompositePart findContainingCompositePart(MPart part) { |
| if (part == null) { |
| return null; |
| } |
| |
| MUIElement curParent = part.getParent(); |
| while (curParent != null && !(curParent instanceof MCompositePart)) { |
| curParent = curParent.getParent(); |
| } |
| |
| return (MCompositePart) curParent; |
| } |
| |
| private void unsplitPart(MCompositePart compositePart) { |
| if (compositePart == null) { |
| return; |
| } |
| |
| List<MPart> innerElements = ms.findElements(compositePart, null, MPart.class, null); |
| if (innerElements.size() < 3) { |
| return; |
| } |
| |
| MPart originalEditor = innerElements.get(1); // '0' is the composite part |
| |
| // Close the cloned editor *before* removing it from the model |
| MPart clonedEditor = innerElements.get(2); |
| clonedEditor.setToBeRendered(false); |
| |
| MElementContainer<MUIElement> compParent = compositePart.getParent(); |
| int index = compParent.getChildren().indexOf(compositePart); |
| compParent.getChildren().remove(compositePart); |
| originalEditor.getParent().getChildren().remove(originalEditor); |
| compParent.getChildren().add(index, originalEditor); |
| |
| if (ps.getActivePart() == originalEditor) { |
| ps.activate(null); |
| } |
| ps.activate(originalEditor); |
| } |
| |
| private MCompositePart createCompositePart(MPart originalPart) { |
| MCompositePart compPart = ms.createModelElement(MCompositePart.class); |
| compPart.setElementId("Split Host(" + originalPart.getLabel() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ |
| compPart.setLabel(originalPart.getLabel()); |
| compPart.setTooltip(originalPart.getTooltip()); |
| compPart.setIconURI(originalPart.getIconURI()); |
| compPart.setCloseable(true); |
| compPart.setContributionURI(SplitHost.SPLIT_HOST_CONTRIBUTOR_URI); |
| |
| // Check if icon from MPart was overridden |
| Object overriddenImage = originalPart.getTransientData().get(IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY); |
| if (overriddenImage != null) { |
| compPart.getTransientData().put(IPresentationEngine.OVERRIDE_ICON_IMAGE_KEY, overriddenImage); |
| } |
| |
| // Always remove the composite part from the model |
| compPart.getTags().add(EPartService.REMOVE_ON_HIDE_TAG); |
| |
| return compPart; |
| } |
| |
| void splitPart(MPart partToSplit, boolean horizontal) { |
| MElementContainer<MUIElement> parent = partToSplit.getParent(); |
| int index = parent.getChildren().indexOf(partToSplit); |
| |
| MPart editorClone = (MPart) ms.cloneElement(partToSplit, null); |
| |
| MCompositePart compPart = createCompositePart(partToSplit); |
| |
| // Add the new composite part to the model |
| compPart.getChildren().add(editorClone); |
| compPart.setSelectedElement(editorClone); |
| parent.getChildren().add(index, compPart); |
| parent.setSelectedElement(compPart); |
| |
| // Now, add the original part into the composite |
| int orientation = horizontal ? EModelService.ABOVE : EModelService.LEFT_OF; |
| ms.insert(partToSplit, editorClone, orientation, 0.5f); |
| |
| ps.activate(partToSplit); |
| } |
| } |