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 *******************************************************************************/ 14 package org.eclipse.ltk.internal.ui.refactoring; 15 16 import java.util.ArrayList; 17 import java.util.List; 18 19 import org.eclipse.core.runtime.Assert; 20 import org.eclipse.core.runtime.CoreException; 21 22 import org.eclipse.jface.text.IRegion; 23 24 import org.eclipse.ltk.core.refactoring.Change; 25 import org.eclipse.ltk.core.refactoring.GroupCategory; 26 import org.eclipse.ltk.core.refactoring.GroupCategorySet; 27 import org.eclipse.ltk.core.refactoring.TextEditBasedChange; 28 import org.eclipse.ltk.core.refactoring.TextEditBasedChangeGroup; 29 import org.eclipse.ltk.ui.refactoring.IChangePreviewViewer; 30 import org.eclipse.ltk.ui.refactoring.TextEditChangeNode; 31 import org.eclipse.ltk.ui.refactoring.TextEditChangeNode.ChildNode; 32 33 public abstract class InternalLanguageElementNode extends TextEditChangeNode.ChildNode { 34 35 private List<ChildNode> fChildren; 36 private GroupCategorySet fGroupCategories; 37 InternalLanguageElementNode(PreviewNode parent)38 protected InternalLanguageElementNode(PreviewNode parent) { 39 super(parent); 40 } 41 42 @Override getChangePreviewViewerDescriptor()43 ChangePreviewViewerDescriptor getChangePreviewViewerDescriptor() throws CoreException { 44 InternalTextEditChangeNode element= getTextEditChangeNode(); 45 if (element == null) 46 return null; 47 return element.getChangePreviewViewerDescriptor(); 48 } 49 50 @Override feedInput(IChangePreviewViewer viewer, List<GroupCategory> categories)51 void feedInput(IChangePreviewViewer viewer, List<GroupCategory> categories) throws CoreException { 52 InternalTextEditChangeNode element= getTextEditChangeNode(); 53 if (element != null) { 54 Change change= element.getChange(); 55 if (change instanceof TextEditBasedChange) { 56 List<TextEditBasedChangeGroup> groups= collectTextEditBasedChangeGroups(categories); 57 viewer.setInput(TextEditChangePreviewViewer.createInput(change, 58 groups.toArray(new TextEditBasedChangeGroup[groups.size()]), 59 getTextRange())); 60 } 61 } else { 62 viewer.setInput(null); 63 } 64 } 65 66 @Override setEnabled(boolean enabled)67 void setEnabled(boolean enabled) { 68 for (PreviewNode element : fChildren) { 69 element.setEnabled(enabled); 70 } 71 } 72 73 @Override setEnabledShallow(boolean enabled)74 void setEnabledShallow(boolean enabled) { 75 // do nothing. We don't manage an own enablement state. 76 } 77 78 @Override getActive()79 int getActive() { 80 Assert.isTrue(fChildren.size() > 0); 81 int result= ((PreviewNode)fChildren.get(0)).getActive(); 82 for (int i= 1; i < fChildren.size(); i++) { 83 PreviewNode element= fChildren.get(i); 84 result= PreviewNode.ACTIVATION_TABLE[element.getActive()][result]; 85 if (result == PreviewNode.PARTLY_ACTIVE) 86 break; 87 } 88 return result; 89 } 90 91 @Override getChildren()92 PreviewNode[] getChildren() { 93 if (fChildren == null) 94 return PreviewNode.EMPTY_CHILDREN; 95 return fChildren.toArray(new PreviewNode[fChildren.size()]); 96 } 97 98 @Override hasOneGroupCategory(List<GroupCategory> categories)99 boolean hasOneGroupCategory(List<GroupCategory> categories) { 100 if (fChildren == null) 101 return false; 102 return getGroupCategorySet().containsOneCategory(categories); 103 } 104 105 @Override hasDerived()106 boolean hasDerived() { 107 if (fChildren == null) 108 return false; 109 for (PreviewNode node : fChildren) { 110 if (node.hasDerived()) 111 return true; 112 } 113 return false; 114 } 115 getGroupCategorySet()116 private GroupCategorySet getGroupCategorySet() { 117 if (fGroupCategories == null) { 118 fGroupCategories= GroupCategorySet.NONE; 119 for (PreviewNode node : fChildren) { 120 GroupCategorySet other= null; 121 if (node instanceof TextEditGroupNode) { 122 other= ((TextEditGroupNode)node).getGroupCategorySet(); 123 } else if (node instanceof InternalLanguageElementNode) { 124 other= ((InternalLanguageElementNode)node).getGroupCategorySet(); 125 } else { 126 Assert.isTrue(false, "Shouldn't happen"); //$NON-NLS-1$ 127 } 128 fGroupCategories= GroupCategorySet.union(fGroupCategories, other); 129 } 130 } 131 return fGroupCategories; 132 } 133 internalAddChild(ChildNode child)134 protected void internalAddChild(ChildNode child) { 135 if (fChildren == null) 136 fChildren= new ArrayList<>(2); 137 fChildren.add(child); 138 } 139 collectTextEditBasedChangeGroups(List<GroupCategory> categories)140 private List<TextEditBasedChangeGroup> collectTextEditBasedChangeGroups(List<GroupCategory> categories) { 141 List<TextEditBasedChangeGroup> result= new ArrayList<>(10); 142 for (PreviewNode child : getChildren()) { 143 if (child instanceof TextEditGroupNode) { 144 TextEditBasedChangeGroup changeGroup= ((TextEditGroupNode)child).getChangeGroup(); 145 if (categories == null || changeGroup.getGroupCategorySet().containsOneCategory(categories)) 146 result.add(changeGroup); 147 } else if (child instanceof InternalLanguageElementNode) { 148 result.addAll(((InternalLanguageElementNode)child).collectTextEditBasedChangeGroups(categories)); 149 } 150 } 151 return result; 152 } 153 154 /** 155 * Returns the text region the of this language element node. 156 * 157 * @return the text region of this language element node 158 * @throws CoreException if the source region can't be obtained 159 */ getTextRange()160 public abstract IRegion getTextRange() throws CoreException; 161 } 162