1 /******************************************************************************* 2 * Copyright (c) 2006, 2011 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 package org.eclipse.compare.structuremergeviewer; 15 16 import org.eclipse.compare.IEditableContentExtension; 17 import org.eclipse.compare.ISharedDocumentAdapter; 18 import org.eclipse.compare.ITypedElement; 19 import org.eclipse.core.runtime.IAdaptable; 20 import org.eclipse.core.runtime.IStatus; 21 import org.eclipse.jface.text.IDocument; 22 import org.eclipse.swt.graphics.Image; 23 import org.eclipse.swt.widgets.Shell; 24 import org.eclipse.ui.services.IDisposable; 25 26 /** 27 * A node that acts as the root of the tree returned from a {@link StructureCreator}. 28 * This node performs the following tasks tasks: 29 * <ol> 30 * <li>It adapts to an {@link ISharedDocumentAdapter} that provides the proper 31 * document key (@see {@link #getAdapter(Class)}).</li> 32 * <li>It invokes {@link IStructureCreator#save(IStructureComparator, Object)} 33 * when {@link #nodeChanged(DocumentRangeNode)} is called.</li> 34 * <li>It disposes of the {@link IDisposable} provided in the constructor when 35 * {@link #dispose()} is called.</li> 36 * </ol> 37 * <p> 38 * This class may be subclassed by clients. 39 * 40 * @since 3.3 41 */ 42 public class StructureRootNode extends DocumentRangeNode implements IDisposable, ITypedElement { 43 /** 44 * The integer constant (value <code>0</code>) that is used as the type code of the root node. 45 * @see #getTypeCode() 46 */ 47 public static final int ROOT_TYPE = 0; 48 49 /** 50 * The string constant (value <code>"root"</code>) that is used as the id of the root node. 51 * @see #getId() 52 */ 53 public static final String ROOT_ID = "root"; //$NON-NLS-1$ 54 55 private final Object fInput; 56 private final StructureCreator fCreator; 57 private ISharedDocumentAdapter fAdapter; 58 59 /** 60 * Create the structure root node. 61 * @param document the document 62 * @param input the input associated with the document 63 * @param creator the structure creator that is creating the node 64 * @param adapter the shared document adapter from which the document was obtained or <code>null</code> 65 * if the document was not obtained from an {@link ISharedDocumentAdapter} 66 */ StructureRootNode(IDocument document, Object input, StructureCreator creator, ISharedDocumentAdapter adapter)67 public StructureRootNode(IDocument document, Object input, StructureCreator creator, ISharedDocumentAdapter adapter) { 68 super(null, ROOT_TYPE, ROOT_ID, document, 0, document.getLength()); 69 fInput = input; 70 fCreator = creator; 71 fAdapter = adapter; 72 } 73 74 @Override dispose()75 public void dispose() { 76 if (fAdapter != null) { 77 fAdapter.disconnect(fInput); 78 } 79 } 80 81 /** 82 * Override {@link IAdaptable#getAdapter(Class)} in order to provide 83 * an {@link ISharedDocumentAdapter} that provides the proper look up key based 84 * on the input from which this structure node was created. 85 * @param adapter the adapter class to look up 86 * @return the object adapted to the given class or <code>null</code> 87 * @see IAdaptable#getAdapter(Class) 88 */ 89 @Override 90 @SuppressWarnings("unchecked") getAdapter(Class<T> adapter)91 public <T> T getAdapter(Class<T> adapter) { 92 if (adapter == ISharedDocumentAdapter.class) { 93 return (T) fAdapter; 94 } 95 return super.getAdapter(adapter); 96 } 97 98 /** 99 * Override in order to invoke {@link IStructureCreator#save(IStructureComparator, Object)} when the 100 * contents of a node have changed. 101 * @param node the changed node 102 */ 103 @Override nodeChanged(DocumentRangeNode node)104 protected void nodeChanged(DocumentRangeNode node) { 105 fCreator.save(this, fInput); 106 } 107 108 @Override replace(ITypedElement child, ITypedElement other)109 public ITypedElement replace(ITypedElement child, ITypedElement other) { 110 // TODO: I believe the parent implementation is flawed but didn't to remove 111 // it in case I was missing something so I overrode it instead 112 nodeChanged(this); 113 return child; 114 } 115 116 @Override getImage()117 public Image getImage() { 118 return null; 119 } 120 121 @Override getName()122 public String getName() { 123 return getId(); 124 } 125 126 @Override getType()127 public String getType() { 128 return FOLDER_TYPE; 129 } 130 131 @Override isReadOnly()132 public boolean isReadOnly() { 133 if (fInput instanceof IEditableContentExtension) { 134 IEditableContentExtension ext = (IEditableContentExtension) fInput; 135 return ext.isReadOnly(); 136 } 137 return super.isReadOnly(); 138 } 139 140 @Override validateEdit(Shell shell)141 public IStatus validateEdit(Shell shell) { 142 if (fInput instanceof IEditableContentExtension) { 143 IEditableContentExtension ext = (IEditableContentExtension) fInput; 144 return ext.validateEdit(shell); 145 } 146 return super.validateEdit(shell); 147 } 148 149 } 150