1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ide.eclipse.adt.internal.editors.layout.gle2; 18 19 import com.android.ide.eclipse.adt.internal.editors.IconFactory; 20 import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; 21 import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; 22 import com.google.common.collect.Lists; 23 24 import org.eclipse.core.resources.IMarker; 25 import org.eclipse.swt.graphics.GC; 26 import org.eclipse.swt.graphics.Image; 27 import org.eclipse.swt.graphics.ImageData; 28 import org.eclipse.swt.graphics.Rectangle; 29 import org.w3c.dom.Node; 30 31 import java.util.Collection; 32 33 /** 34 * The {@link LintOverlay} paints an icon over each view that contains at least one 35 * lint error (unless the view is smaller than the icon) 36 */ 37 public class LintOverlay extends Overlay { 38 /** Approximate size of lint overlay icons */ 39 static final int ICON_SIZE = 8; 40 /** Alpha to draw lint overlay icons with */ 41 private static final int ALPHA = 192; 42 43 private final LayoutCanvas mCanvas; 44 private Image mWarningImage; 45 private Image mErrorImage; 46 47 /** 48 * Constructs a new {@link LintOverlay} 49 * 50 * @param canvas the associated canvas 51 */ LintOverlay(LayoutCanvas canvas)52 public LintOverlay(LayoutCanvas canvas) { 53 mCanvas = canvas; 54 } 55 56 @Override isHiding()57 public boolean isHiding() { 58 return super.isHiding() || !AdtPrefs.getPrefs().isLintOnSave(); 59 } 60 61 @Override paint(GC gc)62 public void paint(GC gc) { 63 LayoutEditorDelegate editor = mCanvas.getEditorDelegate(); 64 Collection<Node> nodes = editor.getLintNodes(); 65 if (nodes != null && !nodes.isEmpty()) { 66 // Copy list before iterating through it to avoid a concurrent list modification 67 // in case lint runs in the background while painting and updates this list 68 nodes = Lists.newArrayList(nodes); 69 ViewHierarchy hierarchy = mCanvas.getViewHierarchy(); 70 Image icon = getWarningIcon(); 71 ImageData imageData = icon.getImageData(); 72 int iconWidth = imageData.width; 73 int iconHeight = imageData.height; 74 CanvasTransform mHScale = mCanvas.getHorizontalTransform(); 75 CanvasTransform mVScale = mCanvas.getVerticalTransform(); 76 77 // Right/bottom edges of the canvas image; don't paint overlays outside of 78 // that. (With for example RelativeLayouts with margins rendered on smaller 79 // screens than they are intended for this can happen.) 80 int maxX = mHScale.translate(0) + mHScale.getScaledImgSize(); 81 int maxY = mVScale.translate(0) + mVScale.getScaledImgSize(); 82 83 int oldAlpha = gc.getAlpha(); 84 try { 85 gc.setAlpha(ALPHA); 86 for (Node node : nodes) { 87 CanvasViewInfo vi = hierarchy.findViewInfoFor(node); 88 if (vi != null) { 89 Rectangle bounds = vi.getAbsRect(); 90 int x = mHScale.translate(bounds.x); 91 int y = mVScale.translate(bounds.y); 92 int w = mHScale.scale(bounds.width); 93 int h = mVScale.scale(bounds.height); 94 if (w < iconWidth || h < iconHeight) { 95 // Don't draw badges on tiny widgets (including those 96 // that aren't tiny but are zoomed out too far) 97 continue; 98 } 99 100 x += w - iconWidth; 101 y += h - iconHeight; 102 103 if (x > maxX || y > maxY) { 104 continue; 105 } 106 107 boolean isError = false; 108 IMarker marker = editor.getIssueForNode(vi.getUiViewNode()); 109 if (marker != null) { 110 int severity = marker.getAttribute(IMarker.SEVERITY, 0); 111 isError = severity == IMarker.SEVERITY_ERROR; 112 } 113 114 icon = isError ? getErrorIcon() : getWarningIcon(); 115 116 gc.drawImage(icon, x, y); 117 } 118 } 119 } finally { 120 gc.setAlpha(oldAlpha); 121 } 122 } 123 } 124 getWarningIcon()125 private Image getWarningIcon() { 126 if (mWarningImage == null) { 127 mWarningImage = IconFactory.getInstance().getIcon("warning-badge"); //$NON-NLS-1$ 128 } 129 130 return mWarningImage; 131 } 132 getErrorIcon()133 private Image getErrorIcon() { 134 if (mErrorImage == null) { 135 mErrorImage = IconFactory.getInstance().getIcon("error-badge"); //$NON-NLS-1$ 136 } 137 138 return mErrorImage; 139 } 140 } 141