diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeOverlay.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeOverlay.java | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeOverlay.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeOverlay.java new file mode 100644 index 000000000..81c03edd5 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeOverlay.java @@ -0,0 +1,150 @@ +/* + * 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.annotations.VisibleForTesting; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Rectangle; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * The {@link IncludeOverlay} class renders masks to -partially- hide everything outside + * an included file's own content. This overlay is in use when you are editing an included + * file shown within a different file's context (e.g. "Show In > other"). + */ +public class IncludeOverlay extends Overlay { + /** Mask transparency - 0 is transparent, 255 is opaque */ + private static final int MASK_TRANSPARENCY = 160; + + /** The associated {@link LayoutCanvas}. */ + private LayoutCanvas mCanvas; + + /** + * Constructs an {@link IncludeOverlay} tied to the given canvas. + * + * @param canvas The {@link LayoutCanvas} to paint the overlay over. + */ + public IncludeOverlay(LayoutCanvas canvas) { + mCanvas = canvas; + } + + @Override + public void paint(GC gc) { + ViewHierarchy viewHierarchy = mCanvas.getViewHierarchy(); + List<Rectangle> includedBounds = viewHierarchy.getIncludedBounds(); + if (includedBounds == null || includedBounds.size() == 0) { + // We don't support multiple included children yet. When that works, + // this code should use a BSP tree to figure out which regions to paint + // to leave holes in the mask. + return; + } + + Image image = mCanvas.getImageOverlay().getImage(); + if (image == null) { + return; + } + + int oldAlpha = gc.getAlpha(); + gc.setAlpha(MASK_TRANSPARENCY); + Color bg = gc.getDevice().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); + gc.setBackground(bg); + + CanvasViewInfo root = viewHierarchy.getRoot(); + Rectangle whole = root.getAbsRect(); + whole = new Rectangle(whole.x, whole.y, whole.width + 1, whole.height + 1); + Collection<Rectangle> masks = subtractRectangles(whole, includedBounds); + + for (Rectangle mask : masks) { + ControlPoint topLeft = LayoutPoint.create(mCanvas, mask.x, mask.y).toControl(); + ControlPoint bottomRight = LayoutPoint.create(mCanvas, mask.x + mask.width, + mask.y + mask.height).toControl(); + int x1 = topLeft.x; + int y1 = topLeft.y; + int x2 = bottomRight.x; + int y2 = bottomRight.y; + + gc.fillRectangle(x1, y1, x2 - x1, y2 - y1); + } + + gc.setAlpha(oldAlpha); + } + + /** + * Given a Rectangle, remove holes from it (specified as a collection of Rectangles) such + * that the result is a list of rectangles that cover everything that is not a hole. + * + * @param rectangle the rectangle to subtract from + * @param holes the holes to subtract from the rectangle + * @return a list of sub rectangles that remain after subtracting out the given list of holes + */ + @VisibleForTesting + static Collection<Rectangle> subtractRectangles( + Rectangle rectangle, Collection<Rectangle> holes) { + List<Rectangle> result = new ArrayList<Rectangle>(); + result.add(rectangle); + + for (Rectangle hole : holes) { + List<Rectangle> tempResult = new ArrayList<Rectangle>(); + for (Rectangle r : result) { + if (hole.intersects(r)) { + // Clip the hole to fit the rectangle bounds + Rectangle h = hole.intersection(r); + + // Split the rectangle + + // Above (includes the NW and NE corners) + if (h.y > r.y) { + tempResult.add(new Rectangle(r.x, r.y, r.width, h.y - r.y)); + } + + // Left (not including corners) + if (h.x > r.x) { + tempResult.add(new Rectangle(r.x, h.y, h.x - r.x, h.height)); + } + + int hx2 = h.x + h.width; + int hy2 = h.y + h.height; + int rx2 = r.x + r.width; + int ry2 = r.y + r.height; + + // Below (includes the SW and SE corners) + if (hy2 < ry2) { + tempResult.add(new Rectangle(r.x, hy2, r.width, ry2 - hy2)); + } + + // Right (not including corners) + if (hx2 < rx2) { + tempResult.add(new Rectangle(hx2, h.y, rx2 - hx2, h.height)); + } + } else { + tempResult.add(r); + } + } + + result = tempResult; + } + + return result; + } +} |