diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LintOverlay.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LintOverlay.java | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LintOverlay.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LintOverlay.java new file mode 100644 index 000000000..ca74493e8 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LintOverlay.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.eclipse.org/org/documents/epl-v10.php + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.ide.eclipse.adt.internal.editors.layout.gle2; + +import com.android.ide.eclipse.adt.internal.editors.IconFactory; +import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; +import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; +import com.google.common.collect.Lists; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.Rectangle; +import org.w3c.dom.Node; + +import java.util.Collection; + +/** + * The {@link LintOverlay} paints an icon over each view that contains at least one + * lint error (unless the view is smaller than the icon) + */ +public class LintOverlay extends Overlay { + /** Approximate size of lint overlay icons */ + static final int ICON_SIZE = 8; + /** Alpha to draw lint overlay icons with */ + private static final int ALPHA = 192; + + private final LayoutCanvas mCanvas; + private Image mWarningImage; + private Image mErrorImage; + + /** + * Constructs a new {@link LintOverlay} + * + * @param canvas the associated canvas + */ + public LintOverlay(LayoutCanvas canvas) { + mCanvas = canvas; + } + + @Override + public boolean isHiding() { + return super.isHiding() || !AdtPrefs.getPrefs().isLintOnSave(); + } + + @Override + public void paint(GC gc) { + LayoutEditorDelegate editor = mCanvas.getEditorDelegate(); + Collection<Node> nodes = editor.getLintNodes(); + if (nodes != null && !nodes.isEmpty()) { + // Copy list before iterating through it to avoid a concurrent list modification + // in case lint runs in the background while painting and updates this list + nodes = Lists.newArrayList(nodes); + ViewHierarchy hierarchy = mCanvas.getViewHierarchy(); + Image icon = getWarningIcon(); + ImageData imageData = icon.getImageData(); + int iconWidth = imageData.width; + int iconHeight = imageData.height; + CanvasTransform mHScale = mCanvas.getHorizontalTransform(); + CanvasTransform mVScale = mCanvas.getVerticalTransform(); + + // Right/bottom edges of the canvas image; don't paint overlays outside of + // that. (With for example RelativeLayouts with margins rendered on smaller + // screens than they are intended for this can happen.) + int maxX = mHScale.translate(0) + mHScale.getScaledImgSize(); + int maxY = mVScale.translate(0) + mVScale.getScaledImgSize(); + + int oldAlpha = gc.getAlpha(); + try { + gc.setAlpha(ALPHA); + for (Node node : nodes) { + CanvasViewInfo vi = hierarchy.findViewInfoFor(node); + if (vi != null) { + Rectangle bounds = vi.getAbsRect(); + int x = mHScale.translate(bounds.x); + int y = mVScale.translate(bounds.y); + int w = mHScale.scale(bounds.width); + int h = mVScale.scale(bounds.height); + if (w < iconWidth || h < iconHeight) { + // Don't draw badges on tiny widgets (including those + // that aren't tiny but are zoomed out too far) + continue; + } + + x += w - iconWidth; + y += h - iconHeight; + + if (x > maxX || y > maxY) { + continue; + } + + boolean isError = false; + IMarker marker = editor.getIssueForNode(vi.getUiViewNode()); + if (marker != null) { + int severity = marker.getAttribute(IMarker.SEVERITY, 0); + isError = severity == IMarker.SEVERITY_ERROR; + } + + icon = isError ? getErrorIcon() : getWarningIcon(); + + gc.drawImage(icon, x, y); + } + } + } finally { + gc.setAlpha(oldAlpha); + } + } + } + + private Image getWarningIcon() { + if (mWarningImage == null) { + mWarningImage = IconFactory.getInstance().getIcon("warning-badge"); //$NON-NLS-1$ + } + + return mWarningImage; + } + + private Image getErrorIcon() { + if (mErrorImage == null) { + mErrorImage = IconFactory.getInstance().getIcon("error-badge"); //$NON-NLS-1$ + } + + return mErrorImage; + } +} |