| 1 | /******************************************************************************* |
|---|---|
| 2 | * Copyright (c) 2000, 2018 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.jdt.astview.views; |
| 16 | |
| 17 | import java.util.List; |
| 18 | |
| 19 | import org.eclipse.swt.SWT; |
| 20 | import org.eclipse.swt.graphics.Color; |
| 21 | import org.eclipse.swt.graphics.Font; |
| 22 | import org.eclipse.swt.graphics.FontData; |
| 23 | import org.eclipse.swt.graphics.Image; |
| 24 | import org.eclipse.swt.widgets.Display; |
| 25 | |
| 26 | import org.eclipse.jface.resource.JFaceResources; |
| 27 | import org.eclipse.jface.viewers.IColorProvider; |
| 28 | import org.eclipse.jface.viewers.IFontProvider; |
| 29 | import org.eclipse.jface.viewers.LabelProvider; |
| 30 | import org.eclipse.jface.viewers.LabelProviderChangedEvent; |
| 31 | |
| 32 | import org.eclipse.ui.PlatformUI; |
| 33 | |
| 34 | import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; |
| 35 | |
| 36 | import org.eclipse.ui.editors.text.EditorsUI; |
| 37 | |
| 38 | import org.eclipse.jdt.core.Signature; |
| 39 | import org.eclipse.jdt.core.dom.ASTNode; |
| 40 | |
| 41 | public class ASTViewLabelProvider extends LabelProvider implements IColorProvider, IFontProvider { |
| 42 | private int fSelectionStart; |
| 43 | private int fSelectionLength; |
| 44 | |
| 45 | private final Color fBlue, fRed, fDarkGray, fDarkGreen, fDarkRed; |
| 46 | private final Font fBold; |
| 47 | |
| 48 | //to dispose: |
| 49 | private final Font fAllocatedBoldItalic; |
| 50 | private final Color fLightRed; |
| 51 | private Color fSelectedElemBGColor; |
| 52 | |
| 53 | public ASTViewLabelProvider() { |
| 54 | fSelectionStart= -1; |
| 55 | fSelectionLength= -1; |
| 56 | |
| 57 | Display display= Display.getCurrent(); |
| 58 | |
| 59 | fRed= display.getSystemColor(SWT.COLOR_RED); |
| 60 | fDarkGray= display.getSystemColor(SWT.COLOR_DARK_GRAY); |
| 61 | fBlue= display.getSystemColor(SWT.COLOR_DARK_BLUE); |
| 62 | fDarkGreen= display.getSystemColor(SWT.COLOR_DARK_GREEN); |
| 63 | fDarkRed= display.getSystemColor(SWT.COLOR_DARK_RED); |
| 64 | |
| 65 | fSelectedElemBGColor= new Color(display, 232, 242, 254); |
| 66 | String currLineColor= EditorsUI.getPreferenceStore().getString(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR); |
| 67 | String[] rgb= currLineColor.split(","); //$NON-NLS-1$ |
| 68 | if (rgb.length == 3) { |
| 69 | try { |
| 70 | fSelectedElemBGColor= new Color(display, Integer.parseInt(rgb[0]), Integer.parseInt(rgb[1]), Integer.parseInt(rgb[2])); |
| 71 | } catch (NumberFormatException e) { |
| 72 | // do nothing, colour would remain the backup value |
| 73 | } |
| 74 | } |
| 75 | fLightRed= new Color(display, 255, 190, 190); |
| 76 | |
| 77 | fBold= PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getFontRegistry().getBold(JFaceResources.DEFAULT_FONT); |
| 78 | FontData[] fontData= fBold.getFontData(); |
| 79 | for (FontData fd : fontData) { |
| 80 | fd.setStyle(fd.getStyle() | SWT.ITALIC); |
| 81 | } |
| 82 | fAllocatedBoldItalic= new Font(display, fontData); |
| 83 | } |
| 84 | |
| 85 | public void setSelectedRange(int start, int length) { |
| 86 | fSelectionStart= start; |
| 87 | fSelectionLength= length; |
| 88 | // could be made more efficient by only updating selected node and parents (of old and new selection) |
| 89 | fireLabelProviderChanged(new LabelProviderChangedEvent(this)); |
| 90 | } |
| 91 | |
| 92 | @Override |
| 93 | public String getText(Object obj) { |
| 94 | StringBuffer buf= new StringBuffer(); |
| 95 | if (obj instanceof ASTNode) { |
| 96 | getNodeType((ASTNode) obj, buf); |
| 97 | } else if (obj instanceof ASTAttribute) { |
| 98 | buf.append(((ASTAttribute) obj).getLabel()); |
| 99 | } |
| 100 | return buf.toString(); |
| 101 | } |
| 102 | |
| 103 | private void getNodeType(ASTNode node, StringBuffer buf) { |
| 104 | buf.append(Signature.getSimpleName(node.getClass().getName())); |
| 105 | buf.append(" ["); //$NON-NLS-1$ |
| 106 | buf.append(node.getStartPosition()); |
| 107 | buf.append("+"); //$NON-NLS-1$ |
| 108 | buf.append(node.getLength()); |
| 109 | buf.append(']'); |
| 110 | if ((node.getFlags() & ASTNode.MALFORMED) != 0) { |
| 111 | buf.append(" (malformed)"); //$NON-NLS-1$ |
| 112 | } |
| 113 | if ((node.getFlags() & ASTNode.RECOVERED) != 0) { |
| 114 | buf.append(" (recovered)"); //$NON-NLS-1$ |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | |
| 119 | @Override |
| 120 | public Image getImage(Object obj) { |
| 121 | if (obj instanceof ASTNode) { |
| 122 | return null; |
| 123 | } else if (obj instanceof ASTAttribute) { |
| 124 | return ((ASTAttribute) obj).getImage(); |
| 125 | } |
| 126 | |
| 127 | return null; |
| 128 | // String imageKey = ISharedImages.IMG_OBJ_ELEMENT; |
| 129 | // if (obj instanceof ASTNode) { |
| 130 | // imageKey = ISharedImages.IMG_OBJ_FOLDER; |
| 131 | // } |
| 132 | // return PlatformUI.getWorkbench().getSharedImages().getImage(imageKey); |
| 133 | } |
| 134 | |
| 135 | @Override |
| 136 | public Color getForeground(Object element) { |
| 137 | if ((element instanceof Error)) |
| 138 | return fRed; |
| 139 | if ((element instanceof ExceptionAttribute) && ((ExceptionAttribute) element).getException() != null) |
| 140 | return fRed; |
| 141 | |
| 142 | if (element instanceof ASTNode) { |
| 143 | ASTNode node= (ASTNode) element; |
| 144 | if ((node.getFlags() & ASTNode.MALFORMED) != 0) { |
| 145 | return fRed; |
| 146 | } |
| 147 | return fDarkGray; |
| 148 | } else if (element instanceof Binding) { |
| 149 | Binding binding= (Binding) element; |
| 150 | if (!binding.isRelevant()) |
| 151 | return fDarkGray; |
| 152 | return fBlue; |
| 153 | } else if (element instanceof NodeProperty) { |
| 154 | return null; // normal color |
| 155 | } else if (element instanceof BindingProperty) { |
| 156 | BindingProperty binding= (BindingProperty) element; |
| 157 | if (!binding.isRelevant()) |
| 158 | return fDarkGray; |
| 159 | return fBlue; |
| 160 | } else if (element instanceof JavaElement) { |
| 161 | JavaElement javaElement= (JavaElement) element; |
| 162 | if (javaElement.getJavaElement() == null || ! javaElement.getJavaElement().exists()) { |
| 163 | return fRed; |
| 164 | } |
| 165 | return fDarkGreen; |
| 166 | } |
| 167 | return fDarkRed; // all extra properties |
| 168 | } |
| 169 | |
| 170 | @Override |
| 171 | public Color getBackground(Object element) { |
| 172 | if (isNotProperlyNested(element)) { |
| 173 | return fLightRed; |
| 174 | } |
| 175 | if (fSelectionStart != -1 && isInside(element)) { |
| 176 | return fSelectedElemBGColor; |
| 177 | } |
| 178 | return null; |
| 179 | } |
| 180 | |
| 181 | private boolean isNotProperlyNested(Object element) { |
| 182 | if (element instanceof ASTNode) { |
| 183 | ASTNode node= (ASTNode) element; |
| 184 | int start= node.getStartPosition(); |
| 185 | int end= start + node.getLength(); |
| 186 | |
| 187 | ASTNode parent= node.getParent(); |
| 188 | if (parent != null) { |
| 189 | int parentstart= parent.getStartPosition(); |
| 190 | int parentend= parentstart + parent.getLength(); |
| 191 | |
| 192 | if (start < parentstart || end > parentend) { |
| 193 | return true; |
| 194 | } |
| 195 | } |
| 196 | } |
| 197 | return false; |
| 198 | } |
| 199 | |
| 200 | private boolean isInsideNode(ASTNode node) { |
| 201 | int start= node.getStartPosition(); |
| 202 | int end= start + node.getLength(); |
| 203 | if (start <= fSelectionStart && (fSelectionStart + fSelectionLength) <= end) { |
| 204 | return true; |
| 205 | } |
| 206 | return false; |
| 207 | } |
| 208 | |
| 209 | private boolean isInside(Object element) { |
| 210 | if (element instanceof ASTNode) { |
| 211 | return isInsideNode((ASTNode) element); |
| 212 | } else if (element instanceof NodeProperty) { |
| 213 | NodeProperty property= (NodeProperty) element; |
| 214 | Object object= property.getNode(); |
| 215 | if (object instanceof ASTNode) { |
| 216 | return isInsideNode((ASTNode) object); |
| 217 | } else if (object instanceof List) { |
| 218 | for (Object child : (List<?>) object) { |
| 219 | if (isInside(child)) { |
| 220 | return true; |
| 221 | } |
| 222 | } |
| 223 | } |
| 224 | } |
| 225 | return false; |
| 226 | } |
| 227 | |
| 228 | @Override |
| 229 | public Font getFont(Object element) { |
| 230 | if (element instanceof ASTNode) { |
| 231 | ASTNode node= (ASTNode) element; |
| 232 | if ((node.getFlags() & ASTNode.RECOVERED) != 0) |
| 233 | return fAllocatedBoldItalic; |
| 234 | else |
| 235 | return fBold; |
| 236 | } |
| 237 | return null; |
| 238 | } |
| 239 | |
| 240 | @Override |
| 241 | public void dispose() { |
| 242 | super.dispose(); |
| 243 | fAllocatedBoldItalic.dispose(); |
| 244 | } |
| 245 | |
| 246 | } |
| 247 |
Members