1 /******************************************************************************* 2 * Copyright (c) 2000, 2015 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 * Nikolay Botev - bug 240651 14 *******************************************************************************/ 15 16 package org.eclipse.ui.part; 17 18 import org.eclipse.core.runtime.IProgressMonitor; 19 import org.eclipse.swt.widgets.Composite; 20 import org.eclipse.ui.IEditorInput; 21 import org.eclipse.ui.IEditorPart; 22 import org.eclipse.ui.IEditorReference; 23 import org.eclipse.ui.IEditorSite; 24 import org.eclipse.ui.IPartListener2; 25 import org.eclipse.ui.IWorkbenchPart; 26 import org.eclipse.ui.IWorkbenchPartReference; 27 import org.eclipse.ui.PartInitException; 28 import org.eclipse.ui.internal.e4.compatibility.E4Util; 29 30 /** 31 * A AbstractMultiEditor is a composite of editors. 32 * 33 * This class is intended to be subclassed. 34 * 35 * @since 3.5 36 */ 37 public abstract class AbstractMultiEditor extends EditorPart { 38 39 private int activeEditorIndex; 40 41 private IEditorPart innerEditors[]; 42 43 private IPartListener2 propagationListener; 44 45 /** 46 * Constructs an editor to contain other editors. 47 */ AbstractMultiEditor()48 public AbstractMultiEditor() { 49 super(); 50 } 51 52 /** 53 * Handles a property change notification from a nested editor. The default 54 * implementation simply forwards the change to listeners on this multi editor 55 * by calling <code>firePropertyChange</code> with the same property id. For 56 * example, if the dirty state of a nested editor changes (property id 57 * <code>ISaveablePart.PROP_DIRTY</code>), this method handles it by firing a 58 * property change event for <code>ISaveablePart.PROP_DIRTY</code> to property 59 * listeners on this multi editor. 60 * <p> 61 * Subclasses may extend or reimplement this method. 62 * </p> 63 * 64 * @param propId the id of the property that changed 65 * @since 3.6 66 */ handlePropertyChange(int propId)67 protected void handlePropertyChange(int propId) { 68 firePropertyChange(propId); 69 } 70 71 /* 72 * @see IEditorPart#doSave(IProgressMonitor) 73 */ 74 @Override doSave(IProgressMonitor monitor)75 public void doSave(IProgressMonitor monitor) { 76 for (IEditorPart e : innerEditors) { 77 e.doSave(monitor); 78 } 79 } 80 81 /* 82 * @see IEditorPart#doSaveAs() 83 */ 84 @Override doSaveAs()85 public void doSaveAs() { 86 // no-op 87 } 88 89 /* 90 * @see IEditorPart#init(IEditorSite, IEditorInput) 91 */ 92 @Override init(IEditorSite site, IEditorInput input)93 public void init(IEditorSite site, IEditorInput input) throws PartInitException { 94 init(site, (MultiEditorInput) input); 95 } 96 97 /** 98 * @param site the editor site 99 * @param input the editor input 100 * @exception PartInitException if this editor was not initialized successfully 101 * 102 * @see IEditorPart#init(IEditorSite, IEditorInput) 103 */ init(IEditorSite site, MultiEditorInput input)104 public void init(IEditorSite site, MultiEditorInput input) throws PartInitException { 105 setInput(input); 106 setSite(site); 107 setPartName(input.getName()); 108 setTitleToolTip(input.getToolTipText()); 109 setupEvents(); 110 } 111 112 /* 113 * @see IEditorPart#isDirty() 114 */ 115 @Override isDirty()116 public boolean isDirty() { 117 for (IEditorPart e : innerEditors) { 118 if (e.isDirty()) { 119 return true; 120 } 121 } 122 return false; 123 } 124 125 /* 126 * @see IEditorPart#isSaveAsAllowed() 127 */ 128 @Override isSaveAsAllowed()129 public boolean isSaveAsAllowed() { 130 return false; 131 } 132 133 /* 134 * @see IWorkbenchPart#setFocus() 135 */ 136 @Override setFocus()137 public void setFocus() { 138 innerEditors[activeEditorIndex].setFocus(); 139 } 140 141 /** 142 * Returns the active inner editor. 143 * 144 * @return the active editor 145 */ getActiveEditor()146 public final IEditorPart getActiveEditor() { 147 return innerEditors[activeEditorIndex]; 148 } 149 150 /** 151 * Returns an array with all inner editors. 152 * 153 * @return the inner editors 154 */ getInnerEditors()155 public final IEditorPart[] getInnerEditors() { 156 return innerEditors; 157 } 158 159 /** 160 * Set the inner editors. 161 * 162 * Should not be called by clients. 163 * 164 * @param children the inner editors of this multi editor 165 * @noreference This method is not intended to be referenced by clients. 166 */ setChildren(IEditorPart[] children)167 public final void setChildren(IEditorPart[] children) { 168 innerEditors = children; 169 activeEditorIndex = 0; 170 171 for (IEditorPart child : children) { 172 child.addPropertyListener((source, propId) -> handlePropertyChange(propId)); 173 } 174 175 innerEditorsCreated(); 176 } 177 178 /** 179 * Called as soon as the inner editors have been created and are available. 180 */ innerEditorsCreated()181 protected abstract void innerEditorsCreated(); 182 183 /** 184 * Activates the given nested editor. 185 * 186 * @param part the nested editor 187 * @since 3.0 188 */ activateEditor(IEditorPart part)189 public void activateEditor(IEditorPart part) { 190 activeEditorIndex = getIndex(part); 191 // IEditorPart e = getActiveEditor(); 192 // EditorSite innerSite = (EditorSite) e.getEditorSite(); 193 // ((WorkbenchPage) innerSite.getPage()).requestActivation(e); 194 E4Util.unsupported("We need to request an activation of this part"); //$NON-NLS-1$ 195 } 196 197 /** 198 * Returns the index of the given nested editor. 199 * 200 * @return the index of the nested editor 201 * @since 3.0 202 */ getIndex(IEditorPart editor)203 protected int getIndex(IEditorPart editor) { 204 for (int i = 0; i < innerEditors.length; i++) { 205 if (innerEditors[i] == editor) { 206 return i; 207 } 208 } 209 return -1; 210 } 211 212 /** 213 * Set up the AbstractMultiEditor to propagate events like partClosed(). 214 * 215 * @since 3.2 216 */ setupEvents()217 private void setupEvents() { 218 propagationListener = new IPartListener2() { 219 @Override 220 public void partActivated(IWorkbenchPartReference partRef) { 221 } 222 223 @Override 224 public void partBroughtToTop(IWorkbenchPartReference partRef) { 225 } 226 227 @Override 228 public void partClosed(IWorkbenchPartReference partRef) { 229 IWorkbenchPart part = partRef.getPart(false); 230 if (part == AbstractMultiEditor.this && innerEditors != null) { 231 // propagate the events 232 E4Util.unsupported("propogate the events needed"); //$NON-NLS-1$ 233 } 234 } 235 236 @Override 237 public void partDeactivated(IWorkbenchPartReference partRef) { 238 } 239 240 @Override 241 public void partOpened(IWorkbenchPartReference partRef) { 242 IWorkbenchPart part = partRef.getPart(false); 243 if (part == AbstractMultiEditor.this && innerEditors != null) { 244 // PartService partService = ((WorkbenchPage) getSite() 245 // .getPage()).getPartService(); 246 // for (int i = 0; i < innerEditors.length; i++) { 247 // IEditorPart editor = innerEditors[i]; 248 // IWorkbenchPartReference innerRef = ((PartSite) editor 249 // .getSite()).getPartReference(); 250 // partService.firePartOpened(innerRef); 251 // } 252 // propagate the events 253 E4Util.unsupported("propogate the events needed"); //$NON-NLS-1$ 254 } 255 } 256 257 @Override 258 public void partHidden(IWorkbenchPartReference partRef) { 259 } 260 261 @Override 262 public void partVisible(IWorkbenchPartReference partRef) { 263 } 264 265 @Override 266 public void partInputChanged(IWorkbenchPartReference partRef) { 267 } 268 }; 269 getSite().getPage().addPartListener(propagationListener); 270 } 271 272 /** 273 * Release the added listener. 274 * 275 * @since 3.2 276 */ 277 @Override dispose()278 public void dispose() { 279 getSite().getPage().removePartListener(propagationListener); 280 super.dispose(); 281 } 282 283 /** 284 * This method is called after createPartControl has been executed and should 285 * return the container for the given inner editor. 286 * 287 * @param innerEditorReference a reference to the inner editor that is being 288 * created. 289 * @return the container in which the inner editor's pane and part controls are 290 * to be created. 291 */ getInnerEditorContainer(IEditorReference innerEditorReference)292 public abstract Composite getInnerEditorContainer(IEditorReference innerEditorReference); 293 294 } 295