Home | History | Annotate | Download | only in gle2
      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 
     23 import org.eclipse.core.resources.IMarker;
     24 import org.eclipse.swt.graphics.GC;
     25 import org.eclipse.swt.graphics.Image;
     26 import org.eclipse.swt.graphics.ImageData;
     27 import org.eclipse.swt.graphics.Rectangle;
     28 import org.w3c.dom.Node;
     29 
     30 import java.util.Collection;
     31 
     32 import lombok.ast.libs.org.parboiled.google.collect.Lists;
     33 
     34 /**
     35  * The {@link LintOverlay} paints an icon over each view that contains at least one
     36  * lint error (unless the view is smaller than the icon)
     37  */
     38 public class LintOverlay extends Overlay {
     39     /** Approximate size of lint overlay icons */
     40     static final int ICON_SIZE = 8;
     41     /** Alpha to draw lint overlay icons with */
     42     private static final int ALPHA = 192;
     43 
     44     private final LayoutCanvas mCanvas;
     45     private Image mWarningImage;
     46     private Image mErrorImage;
     47 
     48     /**
     49      * Constructs a new {@link LintOverlay}
     50      *
     51      * @param canvas the associated canvas
     52      */
     53     public LintOverlay(LayoutCanvas canvas) {
     54         mCanvas = canvas;
     55     }
     56 
     57     @Override
     58     public boolean isHiding() {
     59         return super.isHiding() || !AdtPrefs.getPrefs().isLintOnSave();
     60     }
     61 
     62     @Override
     63     public void paint(GC gc) {
     64         LayoutEditorDelegate editor = mCanvas.getEditorDelegate();
     65         Collection<Node> nodes = editor.getLintNodes();
     66         if (nodes != null && !nodes.isEmpty()) {
     67             // Copy list before iterating through it to avoid a concurrent list modification
     68             // in case lint runs in the background while painting and updates this list
     69             nodes = Lists.newArrayList(nodes);
     70             ViewHierarchy hierarchy = mCanvas.getViewHierarchy();
     71             Image icon = getWarningIcon();
     72             ImageData imageData = icon.getImageData();
     73             int iconWidth = imageData.width;
     74             int iconHeight = imageData.height;
     75             CanvasTransform mHScale = mCanvas.getHorizontalTransform();
     76             CanvasTransform mVScale = mCanvas.getVerticalTransform();
     77 
     78             // Right/bottom edges of the canvas image; don't paint overlays outside of
     79             // that. (With for example RelativeLayouts with margins rendered on smaller
     80             // screens than they are intended for this can happen.)
     81             int maxX = mHScale.translate(0) + mHScale.getScaledImgSize();
     82             int maxY = mVScale.translate(0) + mVScale.getScaledImgSize();
     83 
     84             int oldAlpha = gc.getAlpha();
     85             try {
     86                 gc.setAlpha(ALPHA);
     87                 for (Node node : nodes) {
     88                     CanvasViewInfo vi = hierarchy.findViewInfoFor(node);
     89                     if (vi != null) {
     90                         Rectangle bounds = vi.getAbsRect();
     91                         int x = mHScale.translate(bounds.x);
     92                         int y = mVScale.translate(bounds.y);
     93                         int w = mHScale.scale(bounds.width);
     94                         int h = mVScale.scale(bounds.height);
     95                         if (w < iconWidth || h < iconHeight) {
     96                             // Don't draw badges on tiny widgets (including those
     97                             // that aren't tiny but are zoomed out too far)
     98                             continue;
     99                         }
    100 
    101                         x += w - iconWidth;
    102                         y += h - iconHeight;
    103 
    104                         if (x > maxX || y > maxY) {
    105                             continue;
    106                         }
    107 
    108                         boolean isError = false;
    109                         IMarker marker = editor.getIssueForNode(vi.getUiViewNode());
    110                         if (marker != null) {
    111                             int severity = marker.getAttribute(IMarker.SEVERITY, 0);
    112                             isError = severity == IMarker.SEVERITY_ERROR;
    113                         }
    114 
    115                         icon = isError ? getErrorIcon() : getWarningIcon();
    116 
    117                         gc.drawImage(icon, x, y);
    118                     }
    119                 }
    120             } finally {
    121                 gc.setAlpha(oldAlpha);
    122             }
    123         }
    124     }
    125 
    126     private Image getWarningIcon() {
    127         if (mWarningImage == null) {
    128             mWarningImage = IconFactory.getInstance().getIcon("warning-badge"); //$NON-NLS-1$
    129         }
    130 
    131         return mWarningImage;
    132     }
    133 
    134     private Image getErrorIcon() {
    135         if (mErrorImage == null) {
    136             mErrorImage = IconFactory.getInstance().getIcon("error-badge");     //$NON-NLS-1$
    137         }
    138 
    139         return mErrorImage;
    140     }
    141 }
    142