| /******************************************************************************* |
| * Copyright (c) 2012 Rushan R. Gilmullin and others. |
| * All rights reserved. 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: |
| * Rushan R. Gilmullin - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.osbp.e4extension.impl; |
| |
| import java.lang.reflect.Method; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import javax.inject.Inject; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.e4.core.contexts.ContextInjectionFactory; |
| import org.eclipse.e4.core.contexts.IEclipseContext; |
| import org.eclipse.e4.core.di.annotations.Execute; |
| import org.eclipse.e4.core.services.contributions.IContributionFactory; |
| import org.eclipse.e4.ui.model.application.MApplication; |
| import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor; |
| 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.advanced.MPerspectiveStack; |
| import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder; |
| import org.eclipse.e4.ui.model.application.ui.basic.MInputPart; |
| import org.eclipse.e4.ui.model.application.ui.basic.MPart; |
| import org.eclipse.e4.ui.model.application.ui.basic.MWindow; |
| import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicFactoryImpl; |
| import org.eclipse.e4.ui.model.application.ui.menu.MToolBar; |
| import org.eclipse.e4.ui.workbench.modeling.EModelService; |
| import org.eclipse.e4.ui.workbench.modeling.EPartService; |
| import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.osbp.e4extension.service.EPartServiceExt; |
| |
| import e4modelextension.EditorPartDescriptor; |
| import e4modelextension.VaaclipseApplication; |
| |
| /** |
| * @author rushan |
| * |
| */ |
| public class PartServiceExtImpl implements EPartServiceExt { |
| @Inject |
| private IEclipseContext eclipseContext; |
| |
| @Inject |
| private MApplication application; |
| |
| @Inject |
| EPartService partService; |
| |
| @Inject |
| EModelService modelService; |
| |
| Map<String, Pattern> patterns = new HashMap<String, Pattern>(); |
| |
| private EPartService actualServiceImplementation; |
| |
| @Override |
| public MInputPart createInputPart(String id) { |
| MPartDescriptor descriptor = findDescriptor(id); |
| return createInputPart(descriptor); |
| } |
| |
| private MInputPart createInputPart(MPartDescriptor descriptor) { |
| if (descriptor == null) { |
| return null; |
| } |
| |
| MInputPart part = BasicFactoryImpl.eINSTANCE.createInputPart(); |
| part.setElementId(descriptor.getElementId()); |
| part.getMenus().addAll(EcoreUtil.copyAll(descriptor.getMenus())); |
| if (descriptor.getToolbar() != null) { |
| part.setToolbar((MToolBar) EcoreUtil.copy((EObject) descriptor |
| .getToolbar())); |
| } |
| part.setContributorURI(descriptor.getContributorURI()); |
| // part.setCloseable(descriptor.isCloseable()); |
| part.setCloseable(true); // closable |
| part.setContributionURI(descriptor.getContributionURI()); |
| part.setLabel(descriptor.getLabel()); |
| part.setIconURI(descriptor.getIconURI()); |
| part.setTooltip(descriptor.getTooltip()); |
| part.getHandlers().addAll(EcoreUtil.copyAll(descriptor.getHandlers())); |
| part.getTags().addAll(descriptor.getTags()); |
| part.getBindingContexts().addAll(descriptor.getBindingContexts()); |
| part.getTags().add(EPartService.REMOVE_ON_HIDE_TAG); |
| return part; |
| } |
| |
| @Override |
| public MPartDescriptor findDescriptor(String id) { |
| for (MPartDescriptor descriptor : application.getDescriptors()) { |
| if (descriptor.getElementId().equals(id)) { |
| return descriptor; |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public EditorPartDescriptor findEditorPartDescriptorUsingId(String id) { |
| for (EditorPartDescriptor descriptor : ((VaaclipseApplication) application) |
| .getEditorDescriptors()) { |
| if (descriptor.getElementId().equals(id)) { |
| return descriptor; |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public EditorPartDescriptor findEditorPartDescriptor(String inputUri) { |
| for (EditorPartDescriptor d : ((VaaclipseApplication) application) |
| .getEditorDescriptors()) { |
| if (d.getUriFilter() != null) { |
| String filter = d.getUriFilter().trim(); |
| if (!filter.isEmpty()) { |
| if (!patterns.containsKey(filter)) { |
| patterns.put(filter, Pattern.compile(filter)); |
| } |
| Pattern pattern = patterns.get(filter); |
| Matcher matcher = pattern.matcher(inputUri); |
| if (matcher.matches()) { |
| return d; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public MInputPart openUri(MElementContainer<?> area, String inputUri) { |
| EditorPartDescriptor editorPartDescriptor = findEditorPartDescriptor(inputUri); |
| return openUri(inputUri, editorPartDescriptor, area); |
| } |
| |
| @Override |
| public MInputPart openUri(String inputUri, |
| EditorPartDescriptor editorPartDescriptor, MElementContainer<?> area) { |
| MInputPart part = ensurePartAdded(getWindow(), area, |
| editorPartDescriptor, inputUri); |
| |
| // ATTENTION!!! We should use the EPartService showPart method ONLY if |
| // all contexts are crated (i.e. model is rendered) |
| // But this method (openURI) should be usable when model is not |
| // rendered. So we check the context and if it is created we use |
| // servive methods. |
| if (application.getContext() != null) |
| partService.showPart(part, PartState.ACTIVATE); |
| else // otherwise just select it in its container |
| { |
| MPlaceholder partPh = modelService.findPlaceholderFor(getWindow(), |
| part); |
| if (partPh != null) { |
| MElementContainer<MUIElement> parent = partPh.getParent(); |
| parent.setSelectedElement(partPh); |
| } else { |
| MElementContainer<MUIElement> parent = part.getParent(); |
| parent.setSelectedElement(part); |
| } |
| } |
| return part; |
| } |
| |
| @Override |
| public MInputPart openUri(String inputUri) { |
| return this.openUri((MElementContainer<?>) null, inputUri); |
| } |
| |
| @Override |
| public MInputPart openUri(String inputUri, EditorPartDescriptor descriptor) { |
| return this.openUri(inputUri, descriptor, null); |
| } |
| |
| @Override |
| public MInputPart openUri(String inputUri, String editorDescriptorId) { |
| EditorPartDescriptor d = findEditorPartDescriptorUsingId(editorDescriptorId); |
| if (d != null) { |
| return openUri(inputUri, d); |
| } else |
| return null; |
| } |
| |
| @Override |
| public void closeUri(String inputUri, boolean saveBeforeClose) { |
| MInputPart part = findPart(getWindow(), inputUri); |
| |
| if (part == null) |
| return; |
| |
| if (saveBeforeClose) { |
| IEclipseContext partContext = part.getContext(); |
| if (partContext == null) |
| partContext = modelService.getContainingContext(part); |
| |
| // Allow closes to be 'canceled' |
| EPartService partService = (EPartService) partContext |
| .get(EPartService.class.getName()); |
| if (partService.savePart(part, true)) { |
| partService.hidePart(part, true); |
| } |
| } else { |
| partService.hidePart(part, true); |
| } |
| } |
| |
| private MInputPart ensurePartAdded(MWindow window, |
| MElementContainer<?> area, |
| EditorPartDescriptor editorPartDescriptor, String inputUri) { |
| MInputPart part = findPart(window, inputUri); |
| |
| if (part == null) {// else we create new part and add it with specified |
| // logic |
| |
| // create part |
| part = addInputPart(window, area, editorPartDescriptor, inputUri); |
| |
| // now part is added to window, so we all work is done |
| } |
| |
| return part; |
| } |
| |
| private MInputPart addInputPart(MWindow window, MElementContainer<?> area, |
| EditorPartDescriptor editorPartDescriptor, String inputUri) { |
| MInputPart part; |
| part = createInputPart(editorPartDescriptor); |
| part.setInputURI(inputUri); |
| |
| // create context for add logic and set context info |
| IEclipseContext localContext = eclipseContext.createChild(); |
| localContext.set(MPart.class, part); |
| localContext.set(MElementContainer.class, area); |
| localContext.set(MInputPart.class, part); |
| localContext.set(MWindow.class, window); |
| |
| // obtain adding logic |
| IContributionFactory contributionFactory = (IContributionFactory) localContext |
| .get(IContributionFactory.class.getName()); |
| Object addLogic = contributionFactory.create( |
| editorPartDescriptor.getPartAddingLogicUri(), localContext); |
| |
| // execute adding logic |
| ContextInjectionFactory.invoke(addLogic, Execute.class, localContext); |
| return part; |
| } |
| |
| @Override |
| public MInputPart openNewEditor(EditorPartDescriptor descriptor) { |
| return addInputPart(getWindow(), null, descriptor, null); |
| } |
| |
| @Override |
| public MInputPart openNewEditor(String descriptorId) { |
| EditorPartDescriptor d = findEditorPartDescriptorUsingId(descriptorId); |
| if (d == null) |
| return null; |
| return openNewEditor(d); |
| } |
| |
| private MInputPart findPart(MWindow window, String inputUri) { |
| MPerspectiveStack stack = null; |
| for (MUIElement e : window.getChildren()) { |
| if (e instanceof MPerspectiveStack) { |
| stack = (MPerspectiveStack) e; |
| break; |
| } |
| } |
| |
| MPerspective persp = stack != null ? stack.getSelectedElement() : null; |
| |
| MElementContainer<?> container = persp != null ? persp : window; |
| |
| List<MPart> parts = modelService.findElements(container, null, |
| MPart.class, null, EModelService.OUTSIDE_PERSPECTIVE |
| | EModelService.IN_ACTIVE_PERSPECTIVE |
| | EModelService.IN_SHARED_AREA); |
| |
| MInputPart part = null; |
| for (MPart p : parts) { |
| if (p instanceof MInputPart) { |
| String _inputUri = ((MInputPart) p).getInputURI(); |
| if (inputUri.equals(_inputUri)) { |
| part = (MInputPart) p; |
| break; |
| } |
| } |
| } |
| return part; |
| } |
| |
| private MWindow getWindow() { |
| if (application.getSelectedElement() != null) |
| return application.getSelectedElement(); |
| List<MWindow> windows = application.getChildren(); |
| if (windows.size() != 0) |
| return windows.get(0); |
| return null; |
| } |
| |
| private EPartService getActualServiceImplementation() { |
| if (actualServiceImplementation != null) |
| return actualServiceImplementation; |
| |
| try { |
| Method getActiveWindowService = partService.getClass() |
| .getDeclaredMethod("getActiveWindowService"); |
| getActiveWindowService.setAccessible(true); |
| actualServiceImplementation = (EPartService) getActiveWindowService |
| .invoke(partService); |
| return actualServiceImplementation; |
| } catch (Exception e) { |
| return null; |
| } |
| } |
| |
| public MPart showPart(String id, PartState partState) { |
| Assert.isNotNull(id); |
| Assert.isNotNull(partState); |
| |
| MPart part = partService.findPart(id); |
| if (part == null) { |
| MPartDescriptor descriptor = findDescriptor(id); |
| |
| try { |
| EPartService actualServiceImplementation = getActualServiceImplementation(); |
| Method createPart = actualServiceImplementation.getClass() |
| .getDeclaredMethod("createPart", MPartDescriptor.class); |
| createPart.setAccessible(true); |
| part = (MPart) createPart.invoke(actualServiceImplementation, |
| descriptor); |
| } catch (Exception ex) { |
| return null; |
| } |
| |
| if (part == null) { |
| return null; |
| } |
| } |
| |
| // TODO - seems to work better that way! |
| return partService.showPart(part, partState); |
| } |
| |
| public MPart addPart(MPart part) { |
| Assert.isNotNull(part); |
| MPart localPart = findPart(part.getElementId()); |
| |
| try { |
| EPartService actualServiceImplementation = getActualServiceImplementation(); |
| Method addPart = actualServiceImplementation.getClass() |
| .getDeclaredMethod("addPart", MPart.class, MPart.class); |
| addPart.setAccessible(true); |
| return (MPart) addPart.invoke(actualServiceImplementation, part, |
| localPart == null ? part : localPart); |
| } catch (Exception ex) { |
| return null; |
| } |
| |
| // return addPart(part, localPart == null ? part : localPart); |
| } |
| |
| public MPart findPart(String id) { |
| List<MPart> parts = getParts(MPart.class, id); |
| return parts.size() > 0 ? parts.get(0) : null; |
| } |
| |
| private <T> List<T> getParts(Class<T> cls, String id) { |
| return modelService.findElements(getWindow(), id, cls, null, |
| EModelService.OUTSIDE_PERSPECTIVE |
| | EModelService.IN_ANY_PERSPECTIVE |
| | EModelService.IN_SHARED_AREA); |
| } |
| } |