/** * <copyright> * * Copyright (c) 2010-2016 Thales Global Services S.A.S. * 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: * Thales Global Services S.A.S. - initial API and implementation * * </copyright> */ package org.eclipse.emf.diffmerge.ui.setup; import java.lang.reflect.InvocationTargetException; import java.util.EventObject; import java.util.HashSet; import java.util.Set; import org.eclipse.compare.CompareConfiguration; import org.eclipse.compare.CompareEditorInput; import org.eclipse.compare.ICompareNavigator; import org.eclipse.compare.INavigatable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.emf.common.command.CommandStackListener; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.common.util.WrappedException; import org.eclipse.emf.diffmerge.api.IComparison; import org.eclipse.emf.diffmerge.api.Role; import org.eclipse.emf.diffmerge.api.scopes.IEditableModelScope; import org.eclipse.emf.diffmerge.api.scopes.IPersistentModelScope; import org.eclipse.emf.diffmerge.diffdata.EComparison; import org.eclipse.emf.diffmerge.diffdata.impl.EComparisonImpl; import org.eclipse.emf.diffmerge.ui.EMFDiffMergeUIPlugin; import org.eclipse.emf.diffmerge.ui.Messages; import org.eclipse.emf.diffmerge.ui.diffuidata.UIComparison; import org.eclipse.emf.diffmerge.ui.diffuidata.util.UidiffdataResourceFactoryImpl; import org.eclipse.emf.diffmerge.ui.specification.IComparisonMethod; import org.eclipse.emf.diffmerge.ui.specification.IModelScopeDefinition; import org.eclipse.emf.diffmerge.ui.util.InconsistencyDialog; import org.eclipse.emf.diffmerge.ui.util.MiscUtil; import org.eclipse.emf.diffmerge.ui.viewers.AbstractComparisonViewer; import org.eclipse.emf.diffmerge.ui.viewers.EMFDiffNode; import org.eclipse.emf.diffmerge.ui.viewers.SelectionBridge; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.xmi.PackageNotFoundException; import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.edit.domain.IEditingDomainProvider; import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider; import org.eclipse.emf.edit.ui.view.ExtendedPropertySheetPage; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.transaction.util.TransactionUtil; import org.eclipse.emf.workspace.ResourceUndoContext; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.ISelectionService; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchSite; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.IPageSite; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.eclipse.ui.views.properties.PropertySheet; /** * A CompareEditorInput dedicated to model Diff/Merge. * @see CompareEditorInput * @author Olivier Constant */ public class EMFDiffMergeEditorInput extends CompareEditorInput { /** The non-null (unless disposed) comparison method **/ protected IComparisonMethod _comparisonMethod; /** The initially null resource that holds the comparison */ protected Resource _comparisonResource; /** The left comparison scope (initially null) **/ protected IEditableModelScope _leftScope; /** The right comparison scope (initially null) **/ protected IEditableModelScope _rightScope; /** The ancestor comparison scope (initially null) **/ protected IEditableModelScope _ancestorScope; /** The initially null viewer */ protected AbstractComparisonViewer _viewer; /** Whether the comparison originally contained differences (initially true) */ private boolean _foundDifferences; /** Whether the editor is dirty (required for compatibility with Indigo) */ //OCO private boolean _isDirty; /** The (initially null) property sheet page to show in the Properties view */ protected PropertySheetPage _propertySheetPage; /** The (initially null) command stack listener on the editing domain, if any */ protected CommandStackListener _commandStackListener; /** The non-null (unless disposed) selection bridge between the viewer and the workbench site */ protected SelectionBridge _selectionBridge; /** The (initially null) compare navigator for the workbench navigation buttons */ private ICompareNavigator _navigator; /** * Constructor * @param method_p a non-null comparison method */ public EMFDiffMergeEditorInput(IComparisonMethod method_p) { super(new CompareConfiguration()); _comparisonMethod = method_p; _leftScope = null; _rightScope = null; _ancestorScope = null; _comparisonResource = null; _foundDifferences = true; _isDirty = false; _navigator = createNavigator(); _selectionBridge = new SelectionBridge(); initializeCompareConfiguration(); } /** * @see org.eclipse.compare.CompareEditorInput#canRunAsJob() */ @Override public boolean canRunAsJob() { return true; } /** * Ensure that the selection provider of the workbench site is the intended one */ protected void checkSelectionProvider() { final IWorkbenchSite site = getSite(); if (site != null && site.getSelectionProvider() != _selectionBridge) { site.setSelectionProvider(_selectionBridge); // Eclipse 4.x compatibility layer workaround: selection changed event propagation ISelectionChangedListener selectionChangedListener = new ISelectionChangedListener() { /** * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ public void selectionChanged(SelectionChangedEvent event_p) { // Force propagation to selection listeners through the selection service ISelectionService service = site.getWorkbenchWindow().getSelectionService(); if (service instanceof ISelectionChangedListener) ((ISelectionChangedListener)service).selectionChanged(event_p); } }; _selectionBridge.addSelectionChangedListener(selectionChangedListener); } } /** * @see org.eclipse.compare.CompareEditorInput#contentsCreated() */ @Override protected void contentsCreated() { super.contentsCreated(); checkSelectionProvider(); _viewer.getControl().addDisposeListener(new DisposeListener() { /** * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent) */ public void widgetDisposed(DisposeEvent ev) { handleDispose(); } }); } /** * @see org.eclipse.compare.CompareEditorInput#contributeToToolBar(org.eclipse.jface.action.ToolBarManager) */ @Override public void contributeToToolBar(ToolBarManager toolBarManager) { // Nothing } /** * @see org.eclipse.compare.CompareEditorInput#createContents(org.eclipse.swt.widgets.Composite) */ @Override public Control createContents(Composite parent_p) { // Create viewer _viewer = _comparisonMethod.createComparisonViewer(parent_p, getActionBars()); // Plug it to the selection provider if (_selectionBridge != null) _viewer.getMultiViewerSelectionProvider().addSelectionChangedListener(_selectionBridge); _viewer.addPropertyChangeListener(new IPropertyChangeListener() { /** * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent event_p) { String propertyName = event_p.getProperty(); if (CompareEditorInput.DIRTY_STATE.equals(propertyName)) { boolean dirty = ((Boolean)event_p.getNewValue()).booleanValue(); setDirty(dirty); } } }); // Create viewer contents _viewer.setInput(getCompareResult()); contentsCreated(); return _viewer.getControl(); } /** * Create and return a navigator * @see EMFDiffMergeEditorInput#getNavigator() * @return a non-null object */ protected ICompareNavigator createNavigator() { return new ICompareNavigator() { /** * @see org.eclipse.compare.ICompareNavigator#selectChange(boolean) */ public boolean selectChange(boolean next_p) { boolean result = false; int change = next_p? INavigatable.NEXT_CHANGE: INavigatable.PREVIOUS_CHANGE; if (_viewer != null) result = _viewer.getNavigatable().selectChange(change); return result; } }; } /** * Generate a title for the editor * @return a potentially null string */ protected String createTitle() { Role leftRole = EMFDiffMergeUIPlugin.getDefault().getDefaultLeftRole(); String leftDesc = _comparisonMethod.getModelScopeDefinition(leftRole).getShortLabel(); String rightDesc = _comparisonMethod.getModelScopeDefinition(leftRole.opposite()).getShortLabel(); String result = String.format(Messages.EMFDiffMergeEditorInput_Title, leftDesc, rightDesc); return result; } /** * Dispose the resources which have been added during the comparison process */ protected void disposeResources() { final EditingDomain domain = getEditingDomain(); final Set<Resource> unloaded = new HashSet<Resource>(); MiscUtil.executeAndForget(domain, new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { if (_comparisonResource != null) { for (EObject root : _comparisonResource.getContents()) { if (root instanceof UIComparison) { UIComparison uiComparison = (UIComparison)root; uiComparison.dispose(); } } _comparisonResource.unload(); domain.getResourceSet().getResources().remove(_comparisonResource); unloaded.add(_comparisonResource); } if (_leftScope instanceof IPersistentModelScope) unloaded.addAll(((IPersistentModelScope)_leftScope).unload()); if (_rightScope instanceof IPersistentModelScope) unloaded.addAll(((IPersistentModelScope)_rightScope).unload()); if (_ancestorScope instanceof IPersistentModelScope) unloaded.addAll(((IPersistentModelScope)_ancestorScope).unload()); } }); if (domain != null) domain.getCommandStack().flush(); if (domain instanceof TransactionalEditingDomain) { for (Resource resource : unloaded) { TransactionUtil.disconnectFromEditingDomain(resource); // Cleaning up Eclipse operation history try { ResourceUndoContext context = new ResourceUndoContext( (TransactionalEditingDomain)domain, resource); PlatformUI.getWorkbench().getOperationSupport().getOperationHistory().dispose( context, true, true, false); } catch (Exception e) { // Workbench being disposed: proceed } } } } /** * @see org.eclipse.compare.CompareEditorInput#flushViewers(org.eclipse.core.runtime.IProgressMonitor) */ @Override protected void flushViewers(IProgressMonitor monitor_p) { _viewer.flush(monitor_p); } /** * Return whether the comparison originally contained differences * @return true by default before the comparison has actually been computed */ public boolean foundDifferences() { return _foundDifferences; } /** * @see org.eclipse.compare.CompareEditorInput#getCompareResult() */ @Override public EMFDiffNode getCompareResult() { return (EMFDiffNode)super.getCompareResult(); } /** * Return the editing domain in which comparison takes place, if any * @return a potentially null editing domain * @see IEditingDomainProvider#getEditingDomain() */ public EditingDomain getEditingDomain() { return _comparisonMethod != null? _comparisonMethod.getEditingDomain(): null; } /** * @see org.eclipse.compare.CompareEditorInput#getNavigator() */ @Override public synchronized ICompareNavigator getNavigator() { return _navigator; } /** * Return a property sheet page for the Properties view if possible * @return a potentially null object */ protected IPropertySheetPage getPropertySheetPage() { if (_propertySheetPage == null) { EditingDomain domain = getEditingDomain(); if (domain instanceof AdapterFactoryEditingDomain) { // Property sheet page AdapterFactoryEditingDomain afDomain = (AdapterFactoryEditingDomain)domain; _propertySheetPage = new PropertySheetPage(afDomain); _propertySheetPage.setPropertySourceProvider( new AdapterFactoryContentProvider(afDomain.getAdapterFactory())); // Command stack listener for property sheet page update _commandStackListener = new CommandStackListener() { public void commandStackChanged(final EventObject event_p) { Shell shell = getShell(); if (shell != null) { shell.getDisplay().asyncExec(new Runnable() { public void run() { if (_propertySheetPage != null && !_propertySheetPage.getControl().isDisposed()) _propertySheetPage.refresh(); } }); } } }; afDomain.getCommandStack().addCommandStackListener(_commandStackListener); } } return _propertySheetPage; } /** * Return the current shell, if available * @return a potentially null shell */ protected Shell getShell() { Shell result = null; IWorkbenchSite site = getSite(); if (site != null) result = site.getShell(); return result; } /** * Return the contextual workbench site, if any * @return a potentially null workbench site */ protected IWorkbenchSite getSite() { IWorkbenchSite result = null; IWorkbenchPart part = getWorkbenchPart(); if (part != null) result = part.getSite(); return result; } /** * @see org.eclipse.emf.common.ui.viewer.IViewerProvider#getViewer() */ public AbstractComparisonViewer getViewer() { return _viewer; // Non-null after createContents(Composite) has returned } /** * @see org.eclipse.compare.CompareEditorInput#handleDispose() */ @Override protected void handleDispose() { _navigator = null; Display display = Display.getDefault(); if (_propertySheetPage != null) display.asyncExec(new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { _propertySheetPage.dispose(); } }); if (_viewer != null) { display.asyncExec(new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { _viewer.setSelection(StructuredSelection.EMPTY, false); if (_selectionBridge != null) { _viewer.getMultiViewerSelectionProvider().removeSelectionChangedListener(_selectionBridge); _selectionBridge.clearListeners(); _selectionBridge = null; } _viewer = null; } }); } if (_commandStackListener != null && getEditingDomain() != null) getEditingDomain().getCommandStack().removeCommandStackListener(_commandStackListener); super.handleDispose(); Runnable disposeBehavior = new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { if (getCompareResult() != null) getCompareResult().dispose(); disposeResources(); if (_comparisonMethod != null) _comparisonMethod.dispose(); _comparisonMethod = null; _ancestorScope = null; _leftScope = null; _rightScope = null; _comparisonResource = null; } }; boolean inUIThread = display.getThread() == Thread.currentThread(); if (inUIThread) BusyIndicator.showWhile(display, disposeBehavior); else disposeBehavior.run(); // Clear the input to avoid memory leak try { super.run(null); } catch (Exception e) { // Nothing } } /** * Display appropriate messages according to the problem that happened during the comparison process */ protected void handleExecutionProblem(Throwable problem_p) { Throwable diagnostic = problem_p; if (diagnostic instanceof WrappedException) diagnostic = ((WrappedException)diagnostic).exception(); String message; if (diagnostic instanceof PackageNotFoundException) { PackageNotFoundException pnfe = (PackageNotFoundException)diagnostic; message = MiscUtil.buildString( Messages.EMFDiffMergeEditorInput_WrongMetamodel, "\n", //$NON-NLS-1$ pnfe.getLocation(), ".\n", //$NON-NLS-1$ Messages.EMFDiffMergeEditorInput_MigrationNeeded); } else { String msg = diagnostic.getLocalizedMessage(); if (msg == null) msg = diagnostic.toString(); message = MiscUtil.buildString( Messages.EMFDiffMergeEditorInput_Failure, "\n", msg); //$NON-NLS-1$ } final Shell shell = getShell(); if (shell != null) { final String finalMessage = message; shell.getDisplay().syncExec(new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { MessageDialog.openError(shell, EMFDiffMergeUIPlugin.LABEL, finalMessage); } }); } } /** * Initialize the CompareConfiguration of this CompareEditorInput */ protected void initializeCompareConfiguration() { CompareConfiguration cc = getCompareConfiguration(); cc.setLeftLabel(_comparisonMethod.getModelScopeDefinition(Role.TARGET).getLabel()); cc.setRightLabel(_comparisonMethod.getModelScopeDefinition(Role.REFERENCE).getLabel()); IModelScopeDefinition ancestorDefinition = _comparisonMethod.getModelScopeDefinition(Role.ANCESTOR); cc.setAncestorLabel((ancestorDefinition == null) ? "" : ancestorDefinition.getLabel()); //$NON-NLS-1$ cc.setLeftEditable(_comparisonMethod.getModelScopeDefinition(Role.TARGET).isEditable()); cc.setRightEditable(_comparisonMethod.getModelScopeDefinition(Role.REFERENCE).isEditable()); } /** * Create and return the comparison * @return a non-null comparison */ protected EComparison initializeComparison() { EComparison result = new EComparisonImpl(_leftScope, _rightScope, _ancestorScope); return result; } /** * Create and return the diff node for the given comparison * @param comparison_p a non-null comparison * @return a non-null diff node */ protected EMFDiffNode initializeDiffNode(EComparison comparison_p) { ResourceSet resourceSet = (getEditingDomain() != null)? getEditingDomain().getResourceSet(): null; if (resourceSet != null) { resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put( EMFDiffMergeUIPlugin.UI_DIFF_DATA_FILE_EXTENSION, new UidiffdataResourceFactoryImpl()); String resourceURI = "platform:/resource/comparison/comparison." + //$NON-NLS-1$ EMFDiffMergeUIPlugin.UI_DIFF_DATA_FILE_EXTENSION; _comparisonResource = resourceSet.createResource(URI.createURI(resourceURI)); } CompareConfiguration cc = getCompareConfiguration(); EMFDiffNode result = new EMFDiffNode( comparison_p, getEditingDomain(), cc.isLeftEditable(), cc.isRightEditable()); result.setReferenceRole(_comparisonMethod.getTwoWayReferenceRole()); return result; } /** * @see org.eclipse.compare.CompareEditorInput#isSaveNeeded() */ @Override public boolean isSaveNeeded() { // Redefined for compatibility with Indigo and synchronization with workbench views checkSelectionProvider(); // For Eclipse 3.x when canRunAsJob() is true return _isDirty; } /** * Load the model scopes * @param monitor_p a non-null monitor for reporting progress */ protected void loadScopes(IProgressMonitor monitor_p) { EditingDomain domain = getEditingDomain(); boolean threeWay = _comparisonMethod.isThreeWay(); Role leftRole = EMFDiffMergeUIPlugin.getDefault().getDefaultLeftRole(); String mainTaskName = Messages.EMFDiffMergeEditorInput_Loading; SubMonitor loadingMonitor = SubMonitor.convert( monitor_p, mainTaskName, threeWay ? 4 : 3); loadingMonitor.worked(1); // Loading left loadingMonitor.subTask(Messages.EMFDiffMergeEditorInput_LoadingLeft); Object leftLoadingContext = (domain != null)? domain: _comparisonMethod.getResourceSet(leftRole); _leftScope = _comparisonMethod.getModelScopeDefinition(leftRole).createScope(leftLoadingContext); if (_leftScope == null) throw new RuntimeException(Messages.EMFDiffMergeEditorInput_LeftScopeNull); if (_leftScope instanceof IPersistentModelScope) { try { ((IPersistentModelScope)_leftScope).load(); } catch (Exception e) { throw new WrappedException(e); } } loadingMonitor.worked(1); if (loadingMonitor.isCanceled()) throw new OperationCanceledException(); // Loading right loadingMonitor.subTask(Messages.EMFDiffMergeEditorInput_LoadingRight); Object rightLoadingContext = (domain != null)? domain: _comparisonMethod.getResourceSet(leftRole.opposite()); _rightScope = _comparisonMethod.getModelScopeDefinition(leftRole.opposite()).createScope(rightLoadingContext); if (_rightScope == null) throw new RuntimeException(Messages.EMFDiffMergeEditorInput_RightScopeNull); if (_rightScope instanceof IPersistentModelScope) { try { ((IPersistentModelScope)_rightScope).load(); } catch (Exception e) { throw new WrappedException(e); } } loadingMonitor.worked(1); if (loadingMonitor.isCanceled()) throw new OperationCanceledException(); // Loading ancestor if (threeWay) { loadingMonitor.subTask(Messages.EMFDiffMergeEditorInput_LoadingAncestor); Object ancestorLoadingContext = (domain != null)? domain: _comparisonMethod.getResourceSet(Role.ANCESTOR); _ancestorScope = _comparisonMethod.getModelScopeDefinition(Role.ANCESTOR).createScope(ancestorLoadingContext); if (_ancestorScope == null) throw new RuntimeException(Messages.EMFDiffMergeEditorInput_AncestorScopeNull); if (_ancestorScope instanceof IPersistentModelScope) { try { ((IPersistentModelScope)_ancestorScope).load(); } catch (Exception e) { throw new WrappedException(e); } } loadingMonitor.worked(1); if (loadingMonitor.isCanceled()) throw new OperationCanceledException(); } } /** * Return whether merge can be considered complete */ public boolean mergeIsComplete() { return !isDirty() && (_viewer.getInput() == null || _viewer.getInput().isEmpty()); } /** * @see org.eclipse.compare.CompareEditorInput#prepareInput(org.eclipse.core.runtime.IProgressMonitor) */ @Override protected Object prepareInput(IProgressMonitor monitor_p) throws InvocationTargetException, InterruptedException { if (monitor_p == null) // True when called from handleDispose() return null; String title = createTitle(); setTitle(title); boolean scopesReady = _leftScope != null; SubMonitor monitor = SubMonitor.convert(monitor_p, EMFDiffMergeUIPlugin.LABEL, 2); EMFDiffNode result = null; try { if (!scopesReady) loadScopes(monitor.newChild(1)); EComparison comparison = initializeComparison(); comparison.compute(_comparisonMethod.getMatchPolicy(), _comparisonMethod.getDiffPolicy(), _comparisonMethod.getMergePolicy(), monitor.newChild(scopesReady? 2: 1)); if (!comparison.isConsistent()) handleInconsistency(comparison); _foundDifferences = comparison.hasRemainingDifferences(); if (_foundDifferences) result = initializeDiffNode(comparison); else handleDispose(); } catch (OperationCanceledException e) { // No user feedback is needed handleDispose(); } catch (Throwable t) { // Cannot load models setMessage(Messages.EMFDiffMergeEditorInput_CannotLoad); handleExecutionProblem(t); handleDispose(); } return result; } /** * Warn the user that the comparison is not consistent due to duplicate match IDs * @see IComparison#isConsistent() * @param comparison_p a non-null inconsistent comparison */ protected void handleInconsistency(final IComparison comparison_p) { final Shell shell = getShell(); if (shell != null) { final int[] pressed = new int[1]; shell.getDisplay().syncExec(new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { MessageDialog dialog = new MessageDialog( shell, EMFDiffMergeUIPlugin.LABEL, null, Messages.InconsistencyDialog_DuplicateIDs, MessageDialog.WARNING, new String[] { IDialogConstants.OK_LABEL, IDialogConstants.SHOW_DETAILS_LABEL }, 0); pressed[0] = dialog.open(); } }); if (0 != pressed[0]) shell.getDisplay().syncExec(new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { InconsistencyDialog dialog = new InconsistencyDialog(shell, comparison_p); dialog.open(); } }); } } /** * @see org.eclipse.compare.CompareEditorInput#run(org.eclipse.core.runtime.IProgressMonitor) */ @Override public void run(IProgressMonitor monitor_p) throws InterruptedException, InvocationTargetException { if (getCompareResult() != null) getCompareResult().dispose(); super.run(monitor_p); if (getCompareResult() != null) { if (foundDifferences()) { // This is done here because the compare result must have been assigned: // directly referencing the UIComparison would result in a memory leak if (_comparisonResource != null) { EditingDomain domain = getEditingDomain(); if (domain != null) { MiscUtil.executeAndForget(domain, new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { _comparisonResource.getContents().add(getCompareResult().getUIComparison()); } }); domain.getCommandStack().flush(); } } } } } /** * @see org.eclipse.compare.CompareEditorInput#setDirty(boolean) */ @Override public void setDirty(boolean dirty_p) { // Redefined for compatibility with Indigo boolean oldDirty = isDirty(); if (dirty_p != oldDirty) { _isDirty = dirty_p; PropertyChangeEvent event = new PropertyChangeEvent( this, DIRTY_STATE, Boolean.valueOf(oldDirty), Boolean.valueOf(_isDirty)); firePropertyChange(event); } } /** * @see org.eclipse.compare.CompareEditorInput#setFocus2() */ @Override public boolean setFocus2() { boolean result = false; if (_viewer != null) result = _viewer.getControl().setFocus(); return result; } /** * A slightly enhanced property sheet page for model elements. */ protected static class PropertySheetPage extends ExtendedPropertySheetPage { /** * Constructor * @param editingDomain_p a non-null editing domain for the elements */ protected PropertySheetPage(AdapterFactoryEditingDomain editingDomain_p) { super(editingDomain_p); } /** * @see org.eclipse.emf.edit.ui.view.ExtendedPropertySheetPage#dispose() */ @Override public void dispose() { super.dispose(); // Unregister properties view as selection listener ISelectionService service = getSite().getWorkbenchWindow().getSelectionService(); service.removeSelectionListener(this); } /** * Return the Properties view if already opened * @param part_p a potentially null workbench part * @return a potentially null object */ protected PropertySheet getPropertySheet(IWorkbenchPart part_p) { PropertySheet result = null; IWorkbenchSite site = part_p.getSite(); if (site != null) { IWorkbenchPage page = site.getPage(); if (page != null) { IViewReference ref = page.findViewReference(IPageLayout.ID_PROP_SHEET); if (ref != null) { IViewPart view = ref.getView(false); if (view instanceof PropertySheet) result = (PropertySheet)view; } } } return result; } /** * @see org.eclipse.ui.part.Page#init(org.eclipse.ui.part.IPageSite) */ @Override public void init(IPageSite pageSite_p) { super.init(pageSite_p); // Register as selection listener ISelectionService service = pageSite_p.getWorkbenchWindow().getSelectionService(); service.addSelectionListener(this); } /** * @see org.eclipse.emf.edit.ui.view.ExtendedPropertySheetPage#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ @Override public void selectionChanged(IWorkbenchPart part_p, ISelection selection_p) { PropertySheet propertiesView = getPropertySheet(part_p); if (propertiesView != null && !propertiesView.isPinned()) { if (!selection_p.isEmpty()) // Do not propagate empty selection super.selectionChanged(part_p, selection_p); } } } }