aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/IncludeOverlay.java
diff options
context:
space:
mode:
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.java150
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;
+ }
+}