1 /******************************************************************************* 2 * Copyright (c) 2000, 2008 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 15 package org.eclipse.ui.internal.texteditor.quickdiff; 16 17 import org.eclipse.core.runtime.Assert; 18 19 import org.eclipse.jface.action.Action; 20 21 import org.eclipse.jface.text.source.IAnnotationModel; 22 import org.eclipse.jface.text.source.IAnnotationModelExtension; 23 import org.eclipse.jface.text.source.IChangeRulerColumn; 24 25 import org.eclipse.ui.IEditorInput; 26 27 import org.eclipse.ui.texteditor.IDocumentProvider; 28 import org.eclipse.ui.texteditor.ITextEditor; 29 import org.eclipse.ui.texteditor.ITextEditorExtension3; 30 import org.eclipse.ui.texteditor.IUpdate; 31 import org.eclipse.ui.texteditor.quickdiff.IQuickDiffReferenceProvider; 32 import org.eclipse.ui.texteditor.quickdiff.ReferenceProviderDescriptor; 33 34 35 /** 36 * Action to set the quick diff reference for the document displayed in the editor. An instance of 37 * this class is created for every extension to the extension point <code>quickdiff.referenceprovider</code>, and for 38 * every editor. It acts as a proxy; its <code>run</code> method installs the reference provider 39 * specified by the extension with the quick diff differ on the current document. 40 * 41 * @since 3.0 42 */ 43 public class ReferenceSelectionAction extends Action implements IUpdate { 44 45 /** The editor we get the document from. */ 46 private ITextEditor fEditor= null; 47 /** The descriptor of the managed extension. */ 48 private final ReferenceProviderDescriptor fDescriptor; 49 /** The implementation of the extension, after it has been loaded. */ 50 private IQuickDiffReferenceProvider fProvider; 51 52 /** 53 * Creates a new instance that will lazily create the implementation provided by the extension. 54 * 55 * @param descriptor describes the extension. 56 * @param editor the editor for which this action is created. 57 */ ReferenceSelectionAction(ReferenceProviderDescriptor descriptor, ITextEditor editor)58 public ReferenceSelectionAction(ReferenceProviderDescriptor descriptor, ITextEditor editor) { 59 super("", AS_RADIO_BUTTON); //$NON-NLS-1$ 60 setChecked(false); 61 setEnabled(true); 62 Assert.isLegal(descriptor != null); 63 fDescriptor= descriptor; 64 fEditor= editor; 65 update(); 66 } 67 68 /** 69 * Creates an instance of the implementation provided by the extension, if none has been created 70 * before. Otherwise, the cached implementation is returned. 71 * @return The <code>IQuickDiffProviderImplementation</code> instance provided by the extension. 72 */ getProvider()73 private IQuickDiffReferenceProvider getProvider() { 74 if (fProvider == null) { 75 fProvider= fDescriptor.createProvider(); 76 } 77 return fProvider; 78 } 79 80 @Override run()81 public void run() { 82 83 DocumentLineDiffer differ= getDiffer(true); // create if needed, so the user does not have to toggle display when he selects a reference 84 if (differ == null) 85 return; 86 87 if (fEditor instanceof ITextEditorExtension3) { 88 ITextEditorExtension3 extension= (ITextEditorExtension3) fEditor; 89 IQuickDiffReferenceProvider provider= getProvider(); 90 if (provider != null) { 91 provider.setActiveEditor(fEditor); 92 if (provider.isEnabled()) { 93 differ.setReferenceProvider(provider); 94 extension.showChangeInformation(true); 95 setEnabled(true); 96 } else 97 setEnabled(false); 98 } 99 } 100 } 101 102 @Override update()103 public void update() { 104 /* two things happen here: 105 * 1: checked state setting - if a provider is already installed, and its id matches 106 * our id, we are in checked state. 107 * 2: enablement - if the extending plugin has been loaded, we check the provider for 108 * enablement and take it as our own. 109 */ 110 setText(fDescriptor.getLabel()); 111 DocumentLineDiffer differ= getDiffer(false); // don't create it if we're not showing 112 setChecked(false); 113 if (differ != null) { 114 IQuickDiffReferenceProvider provider= differ.getReferenceProvider(); 115 if (provider != null && provider.getId().equals(fDescriptor.getId())) { 116 setChecked(true); 117 } 118 } 119 120 if (fDescriptor.isPluginLoaded()) { 121 getProvider(); 122 if (fProvider == null) { 123 setEnabled(false); 124 } else { 125 fProvider.setActiveEditor(fEditor); 126 setEnabled(fProvider.isEnabled()); 127 } 128 } else { 129 // optimistically enable it 130 setEnabled(true); 131 } 132 } 133 134 /** 135 * Fetches the differ installed with the current editor's document's annotation model. If none 136 * is installed yet, and <code>createIfNeeded</code> is true, one is created and attached to the 137 * model. 138 * 139 * @param createIfNeeded when set to <code>true</code>, a new differ will be created if needed. 140 * @return the differ installed with the annotation model, or <code>null</code>. 141 */ getDiffer(boolean createIfNeeded)142 private DocumentLineDiffer getDiffer(boolean createIfNeeded) { 143 // get annotation model 144 if (fEditor == null) 145 return null; 146 147 IDocumentProvider provider= fEditor.getDocumentProvider(); 148 IEditorInput editorInput= fEditor.getEditorInput(); 149 if (provider == null || editorInput == null) 150 return null; 151 152 IAnnotationModel m= provider.getAnnotationModel(editorInput); 153 IAnnotationModelExtension model= null; 154 if (m instanceof IAnnotationModelExtension) { 155 model= (IAnnotationModelExtension)m; 156 } else { 157 return null; 158 } 159 160 // get differ 161 DocumentLineDiffer differ= (DocumentLineDiffer)model.getAnnotationModel(IChangeRulerColumn.QUICK_DIFF_MODEL_ID); 162 163 // create if needed 164 if (differ == null && createIfNeeded) { 165 differ= new DocumentLineDiffer(); 166 model.addAnnotationModel(IChangeRulerColumn.QUICK_DIFF_MODEL_ID, differ); 167 } 168 169 return differ; 170 } 171 } 172