aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse/plugins/com.android.ide.eclipse.adt
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-07-30 07:03:03 -0700
committerTor Norbye <tnorbye@google.com>2012-07-31 09:38:25 -0700
commit68d4aa68f412049e12c644b32f12f4219b9f49d5 (patch)
tree22af60b1e580f1ba1f88afad4422f5783e85c1b9 /eclipse/plugins/com.android.ide.eclipse.adt
parenta7d1df4109bbde358b542931864148ea97eca917 (diff)
downloadsdk-68d4aa68f412049e12c644b32f12f4219b9f49d5.zip
sdk-68d4aa68f412049e12c644b32f12f4219b9f49d5.tar.gz
sdk-68d4aa68f412049e12c644b32f12f4219b9f49d5.tar.bz2
Drop shadows in the layout editor
Change-Id: I83f699da2a9d494938ee73fb2c274c5f8d5ac647
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-b.pngbin0 -> 215 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-bl.pngbin0 -> 397 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-br.pngbin0 -> 406 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-r.pngbin0 -> 207 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-tr.pngbin0 -> 397 bytes
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasTransform.java13
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageOverlay.java74
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageUtils.java182
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java16
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SwtUtils.java68
10 files changed, 337 insertions, 16 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-b.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-b.png
new file mode 100644
index 0000000..68f4f4b
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-b.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-bl.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-bl.png
new file mode 100644
index 0000000..ee7dbe8
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-bl.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-br.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-br.png
new file mode 100644
index 0000000..c45ad77
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-br.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-r.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-r.png
new file mode 100644
index 0000000..4af7a33
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-r.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-tr.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-tr.png
new file mode 100644
index 0000000..1fd0c77
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-tr.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasTransform.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasTransform.java
index e367f9e..5650772 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasTransform.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/CanvasTransform.java
@@ -15,6 +15,8 @@
*/
package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
+import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils.SHADOW_SIZE;
+
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.ScrollBar;
@@ -133,6 +135,17 @@ public class CanvasTransform {
mMargin = 0;
} else if (delta < 2 * DEFAULT_MARGIN) {
mMargin = delta / 2;
+
+ ImageOverlay imageOverlay = mCanvas.getImageOverlay();
+ if (imageOverlay != null && imageOverlay.getShowDropShadow()
+ && delta >= SHADOW_SIZE / 2) {
+ mMargin -= SHADOW_SIZE / 2;
+ // Add a little padding on the top too, if there's room. The shadow assets
+ // include enough padding on the bottom to not make this look clipped.
+ if (mMargin < 4) {
+ mMargin += 4;
+ }
+ }
} else {
mMargin = DEFAULT_MARGIN;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageOverlay.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageOverlay.java
index 3704d8f..e32e475 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageOverlay.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageOverlay.java
@@ -16,6 +16,8 @@
package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
+import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils.SHADOW_SIZE;
+
import com.android.annotations.Nullable;
import com.android.ide.common.api.Rect;
import com.android.ide.common.rendering.api.IImageFactory;
@@ -55,6 +57,9 @@ public class ImageOverlay extends Overlay implements IImageFactory {
/** A pre-scaled version of the image */
private Image mPreScaledImage;
+ /** Whether the rendered image should have a drop shadow */
+ private boolean mShowDropShadow;
+
/** Current background AWT image. This is created by {@link #getImage()}, which is called
* by the LayoutLib. */
private SoftReference<BufferedImage> mAwtImage = new SoftReference<BufferedImage>(null);
@@ -120,6 +125,8 @@ public class ImageOverlay extends Overlay implements IImageFactory {
* @return The corresponding SWT image, or null.
*/
public synchronized Image setImage(BufferedImage awtImage, boolean isAlphaChannelImage) {
+ mShowDropShadow = !isAlphaChannelImage;
+
BufferedImage oldAwtImage = mAwtImage.get();
if (awtImage != oldAwtImage || awtImage == null) {
mAwtImage.clear();
@@ -186,6 +193,17 @@ public class ImageOverlay extends Overlay implements IImageFactory {
return awtImage;
}
+ /**
+ * Returns whether this image overlay should be painted with a drop shadow.
+ * This is usually the case, but not for transparent themes like the dialog
+ * theme (Theme.*Dialog), which already provides its own shadow.
+ *
+ * @return true if the image overlay should be shown with a drop shadow.
+ */
+ public boolean getShowDropShadow() {
+ return mShowDropShadow;
+ }
+
@Override
public synchronized void paint(GC gc) {
if (mImage != null) {
@@ -205,8 +223,10 @@ public class ImageOverlay extends Overlay implements IImageFactory {
// independently from when the image changes.
BufferedImage awtImage = mAwtImage.get();
if (PRESCALE && awtImage != null) {
- if (mPreScaledImage == null ||
- mPreScaledImage.getImageData().width != hi.getScaledImgSize()) {
+ int imageWidth = (mPreScaledImage == null) ? 0
+ : mPreScaledImage.getImageData().width
+ - (mShowDropShadow ? SHADOW_SIZE : 0);
+ if (mPreScaledImage == null || imageWidth != hi.getScaledImgSize()) {
double xScale = hi.getScaledImgSize() / (double) awtImage.getWidth();
double yScale = vi.getScaledImgSize() / (double) awtImage.getHeight();
BufferedImage scaledAwtImage;
@@ -219,10 +239,23 @@ public class ImageOverlay extends Overlay implements IImageFactory {
if (xScale == 1.0 && yScale == 1.0) {
// Scaling to 100% is easy!
scaledAwtImage = awtImage;
+
+ if (mShowDropShadow) {
+ // Just need to draw drop shadows
+ scaledAwtImage = ImageUtils.createRectangularDropShadow(awtImage);
+ }
} else {
- scaledAwtImage = ImageUtils.scale(awtImage, xScale, yScale);
+ if (mShowDropShadow) {
+ scaledAwtImage = ImageUtils.scale(awtImage, xScale, yScale,
+ SHADOW_SIZE, SHADOW_SIZE);
+ ImageUtils.drawRectangleShadow(scaledAwtImage, 0, 0,
+ scaledAwtImage.getWidth() - SHADOW_SIZE,
+ scaledAwtImage.getHeight() - SHADOW_SIZE);
+ } else {
+ scaledAwtImage = ImageUtils.scale(awtImage, xScale, yScale);
+ }
}
- assert scaledAwtImage.getWidth() == hi.getScaledImgSize();
+
if (mPreScaledImage != null && !mPreScaledImage.isDisposed()) {
mPreScaledImage.dispose();
}
@@ -244,16 +277,22 @@ public class ImageOverlay extends Overlay implements IImageFactory {
oldAlias = gc_setAntialias(gc, SWT.ON);
}
- gc.drawImage(
- mImage,
- 0, // srcX
- 0, // srcY
- hi.getImgSize(), // srcWidth
- vi.getImgSize(), // srcHeight
- hi.translate(0), // destX
- vi.translate(0), // destY
- hi.getScaledImgSize(), // destWidth
- vi.getScaledImgSize()); // destHeight
+ int srcX = 0;
+ int srcY = 0;
+ int srcWidth = hi.getImgSize();
+ int srcHeight = vi.getImgSize();
+ int destX = hi.translate(0);
+ int destY = vi.translate(0);
+ int destWidth = hi.getScaledImgSize();
+ int destHeight = vi.getScaledImgSize();
+
+ gc.drawImage(mImage,
+ srcX, srcY, srcWidth, srcHeight,
+ destX, destY, destWidth, destHeight);
+
+ if (mShowDropShadow) {
+ SwtUtils.drawRectangleShadow(gc, destX, destY, destWidth, destHeight);
+ }
if (oldAlias != -2) {
gc_setAntialias(gc, oldAlias);
@@ -356,6 +395,13 @@ public class ImageOverlay extends Overlay implements IImageFactory {
* @return a new {@link SwtReadyBufferedImage} object
*/
private static SwtReadyBufferedImage createImage(int w, int h, Device device) {
+ // NOTE: We can't make this image bigger to accommodate the drop shadow directly
+ // (such that we could paint one into the image after a layoutlib render)
+ // since this image is in the full resolution of the device, and gets scaled
+ // to fit in the layout editor. This would have the net effect of causing
+ // the drop shadow to get zoomed/scaled along with the scene, making a tiny
+ // drop shadow for tablet layouts, a huge drop shadow for tiny QVGA screens, etc.
+
ImageData imageData = new ImageData(w, h, 32,
new PaletteData(0x00FF0000, 0x0000FF00, 0x000000FF));
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageUtils.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageUtils.java
index 5e9ec51..aae1f99 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageUtils.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/ImageUtils.java
@@ -25,6 +25,7 @@ import static com.android.ide.eclipse.adt.AdtUtils.endsWithIgnoreCase;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.api.Rect;
+import com.android.ide.eclipse.adt.AdtPlugin;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
@@ -36,9 +37,13 @@ import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
+import javax.imageio.ImageIO;
+
/**
* Utilities related to image processing.
*/
@@ -328,6 +333,9 @@ public class ImageUtils {
/**
* Creates a drop shadow of a given image and returns a new image which shows the
* input image on top of its drop shadow.
+ * <p>
+ * <b>NOTE: If the shape is rectangular and opaque, consider using
+ * {@link #drawRectangleShadow(Graphics, int, int, int, int)} instead.</b>
*
* @param source the source image to be shadowed
* @param shadowSize the size of the shadow in pixels
@@ -435,6 +443,160 @@ public class ImageUtils {
}
/**
+ * Draws a rectangular drop shadow (of size {@link #SHADOW_SIZE} by
+ * {@link #SHADOW_SIZE} around the given source and returns a new image with
+ * both combined
+ *
+ * @param source the source image
+ * @return the source image with a drop shadow on the bottom and right
+ */
+ public static BufferedImage createRectangularDropShadow(BufferedImage source) {
+ int type = source.getType();
+ if (type == BufferedImage.TYPE_CUSTOM) {
+ type = BufferedImage.TYPE_INT_ARGB;
+ }
+
+ int width = source.getWidth();
+ int height = source.getHeight();
+ BufferedImage image = new BufferedImage(width + SHADOW_SIZE, height + SHADOW_SIZE, type);
+ Graphics g = image.getGraphics();
+ g.drawImage(source, 0, 0, width, height, null);
+ ImageUtils.drawRectangleShadow(image, 0, 0, width, height);
+ g.dispose();
+
+ return image;
+ }
+
+ /**
+ * Draws a drop shadow for the given rectangle into the given context. It
+ * will not draw anything if the rectangle is smaller than a minimum
+ * determined by the assets used to draw the shadow graphics.
+ *
+ * @param image the image to draw the shadow into
+ * @param x the left coordinate of the left hand side of the rectangle
+ * @param y the top coordinate of the top of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ */
+ public static final void drawRectangleShadow(BufferedImage image,
+ int x, int y, int width, int height) {
+ Graphics gc = image.getGraphics();
+ try {
+ drawRectangleShadow(gc, x, y, width, height);
+ } finally {
+ gc.dispose();
+ }
+ }
+
+ /**
+ * The width and height of the drop shadow painted by
+ * {@link #drawRectangleShadow(Graphics, int, int, int, int)}
+ */
+ public static final int SHADOW_SIZE = 20; // DO NOT EDIT. This corresponds to bitmap graphics
+
+ /**
+ * Draws a drop shadow for the given rectangle into the given context. It
+ * will not draw anything if the rectangle is smaller than a minimum
+ * determined by the assets used to draw the shadow graphics.
+ * <p>
+ * This corresponds to
+ * {@link SwtUtils#drawRectangleShadow(org.eclipse.swt.graphics.GC, int, int, int, int)},
+ * but applied to an AWT graphics object instead, such that no image
+ * conversion has to be performed.
+ * <p>
+ * Make sure to keep changes in the visual appearance here in sync with the
+ * AWT version in
+ * {@link SwtUtils#drawRectangleShadow(org.eclipse.swt.graphics.GC, int, int, int, int)}.
+ *
+ * @param gc the graphics context to draw into
+ * @param x the left coordinate of the left hand side of the rectangle
+ * @param y the top coordinate of the top of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ */
+ public static final void drawRectangleShadow(Graphics gc,
+ int x, int y, int width, int height) {
+ if (sShadowBottomLeft == null) {
+ // Shadow graphics. This was generated by creating a drop shadow in
+ // Gimp, using the parameters x offset=10, y offset=10, blur radius=10,
+ // color=black, and opacity=51. These values attempt to make a shadow
+ // that is legible both for dark and light themes, on top of the
+ // canvas background (rgb(150,150,150). Darker shadows would tend to
+ // blend into the foreground for a dark holo screen, and lighter shadows
+ // would be hard to spot on the canvas background. If you make adjustments,
+ // make sure to check the shadow with both dark and light themes.
+ //
+ // After making the graphics, I cut out the top right, bottom left
+ // and bottom right corners as 20x20 images, and these are reproduced by
+ // painting them in the corresponding places in the target graphics context.
+ // I then grabbed a single horizontal gradient line from the middle of the
+ // right edge,and a single vertical gradient line from the bottom. These
+ // are then painted scaled/stretched in the target to fill the gaps between
+ // the three corner images.
+ //
+ // Filenames: bl=bottom left, b=bottom, br=bottom right, r=right, tr=top right
+ sShadowBottomLeft = readImage("shadow-bl.png"); //$NON-NLS-1$
+ sShadowBottom = readImage("shadow-b.png"); //$NON-NLS-1$
+ sShadowBottomRight = readImage("shadow-br.png"); //$NON-NLS-1$
+ sShadowRight = readImage("shadow-r.png"); //$NON-NLS-1$
+ sShadowTopRight = readImage("shadow-tr.png"); //$NON-NLS-1$
+ assert sShadowBottomLeft != null;
+ assert sShadowBottomRight.getWidth() == SHADOW_SIZE;
+ assert sShadowBottomRight.getHeight() == SHADOW_SIZE;
+ }
+
+ int blWidth = sShadowBottomLeft.getWidth();
+ int trHeight = sShadowTopRight.getHeight();
+ if (width < blWidth) {
+ return;
+ }
+ if (height < trHeight) {
+ return;
+ }
+
+ gc.drawImage(sShadowBottomLeft, x, y + height, null);
+ gc.drawImage(sShadowBottomRight, x + width, y + height, null);
+ gc.drawImage(sShadowTopRight, x + width, y, null);
+ gc.drawImage(sShadowBottom,
+ x + sShadowBottomLeft.getWidth(), y + height,
+ x + width, y + height + sShadowBottom.getHeight(),
+ 0, 0, sShadowBottom.getWidth(), sShadowBottom.getHeight(),
+ null);
+ gc.drawImage(sShadowRight,
+ x + width, y + sShadowTopRight.getHeight(),
+ x + width + sShadowRight.getWidth(), y + height,
+ 0, 0, sShadowRight.getWidth(), sShadowRight.getHeight(),
+ null);
+ }
+
+ @Nullable
+ private static BufferedImage readImage(@NonNull String name) {
+ InputStream stream = ImageUtils.class.getResourceAsStream("/icons/" + name); //$NON-NLS-1$
+ if (stream != null) {
+ try {
+ return ImageIO.read(stream);
+ } catch (IOException e) {
+ AdtPlugin.log(e, "Could not read %1$s", name);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ // Dumb API
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private static BufferedImage sShadowBottomLeft;
+ private static BufferedImage sShadowBottom;
+ private static BufferedImage sShadowBottomRight;
+ private static BufferedImage sShadowRight;
+ private static BufferedImage sShadowTopRight;
+
+
+ /**
* Returns a bounding rectangle for the given list of rectangles. If the list is
* empty, the bounding rectangle is null.
*
@@ -546,6 +708,21 @@ public class ImageUtils {
* @return the scaled image
*/
public static BufferedImage scale(BufferedImage source, double xScale, double yScale) {
+ return scale(source, xScale, yScale, 0, 0);
+ }
+
+ /**
+ * Resize the given image
+ *
+ * @param source the image to be scaled
+ * @param xScale x scale
+ * @param yScale y scale
+ * @param rightMargin extra margin to add on the right
+ * @param bottomMargin extra margin to add on the bottom
+ * @return the scaled image
+ */
+ public static BufferedImage scale(BufferedImage source, double xScale, double yScale,
+ int rightMargin, int bottomMargin) {
int sourceWidth = source.getWidth();
int sourceHeight = source.getHeight();
int destWidth = Math.max(1, (int) (xScale * sourceWidth));
@@ -554,11 +731,12 @@ public class ImageUtils {
if (imageType == BufferedImage.TYPE_CUSTOM) {
imageType = BufferedImage.TYPE_INT_ARGB;
}
- BufferedImage scaled = new BufferedImage(destWidth, destHeight, imageType);
+ BufferedImage scaled = new BufferedImage(
+ destWidth + rightMargin, destHeight + bottomMargin, imageType);
Graphics2D g2 = scaled.createGraphics();
g2.setComposite(AlphaComposite.Src);
g2.setColor(new Color(0, true));
- g2.fillRect(0, 0, destWidth, destHeight);
+ g2.fillRect(0, 0, destWidth + rightMargin, destHeight + bottomMargin);
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java
index 542d55e..d33aca1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java
@@ -71,6 +71,7 @@ import org.eclipse.swt.events.MenuDetectListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
@@ -237,6 +238,8 @@ public class LayoutCanvas extends Canvas {
/** Tooltip manager for lint warnings */
private LintTooltipManager mLintTooltipManager;
+ private Color mBackgroundColor;
+
public LayoutCanvas(LayoutEditorDelegate editorDelegate,
RulesEngine rulesEngine,
Composite parent,
@@ -245,6 +248,9 @@ public class LayoutCanvas extends Canvas {
mEditorDelegate = editorDelegate;
mRulesEngine = rulesEngine;
+ mBackgroundColor = new Color(parent.getDisplay(), 150, 150, 150);
+ setBackground(mBackgroundColor);
+
mClipboardSupport = new ClipboardSupport(this, parent);
mHScale = new CanvasTransform(this, getHorizontalBar());
mVScale = new CanvasTransform(this, getVerticalBar());
@@ -480,6 +486,11 @@ public class LayoutCanvas extends Canvas {
mLintOverlay = null;
}
+ if (mBackgroundColor != null) {
+ mBackgroundColor.dispose();
+ mBackgroundColor = null;
+ }
+
mViewHierarchy.dispose();
}
@@ -738,6 +749,11 @@ public class LayoutCanvas extends Canvas {
return;
}
+ if (imageOverlay.getShowDropShadow()) {
+ sceneWidth += 2 * ImageUtils.SHADOW_SIZE;
+ sceneHeight += 2 * ImageUtils.SHADOW_SIZE;
+ }
+
// Reduce the margins if necessary
int hDelta = canvasWidth - sceneWidth;
int hMargin = 0;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SwtUtils.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SwtUtils.java
index 99d6505..64e91be 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SwtUtils.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/SwtUtils.java
@@ -15,7 +15,10 @@
*/
package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
+import static com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils.SHADOW_SIZE;
+
import com.android.ide.common.api.Rect;
+import com.android.ide.eclipse.adt.internal.editors.IconFactory;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.graphics.Device;
@@ -386,4 +389,69 @@ public class SwtUtils {
gc.dispose();
return width;
}
+
+ /**
+ * Draws a drop shadow for the given rectangle into the given context. It
+ * will not draw anything if the rectangle is smaller than a minimum
+ * determined by the assets used to draw the shadow graphics.
+ * <p>
+ * This corresponds to {@link ImageUtils#drawRectangleShadow(Graphics, int, int, int, int)},
+ * but applied directly to an SWT graphics context instead, such that no image conversion
+ * has to be performed.
+ * <p>
+ * Make sure to keep changes in the visual appearance here in sync with the
+ * AWT version in {@link ImageUtils#drawRectangleShadow(Graphics, int, int, int, int)}.
+ *
+ * @param gc the graphics context to draw into
+ * @param x the left coordinate of the left hand side of the rectangle
+ * @param y the top coordinate of the top of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ */
+ public static final void drawRectangleShadow(GC gc, int x, int y, int width, int height) {
+ if (sShadowBottomLeft == null) {
+ IconFactory icons = IconFactory.getInstance();
+ // See ImageUtils.drawRectangleShadow for an explanation of the assets.
+ sShadowBottomLeft = icons.getIcon("shadow-bl"); //$NON-NLS-1$
+ sShadowBottom = icons.getIcon("shadow-b"); //$NON-NLS-1$
+ sShadowBottomRight = icons.getIcon("shadow-br"); //$NON-NLS-1$
+ sShadowRight = icons.getIcon("shadow-r"); //$NON-NLS-1$
+ sShadowTopRight = icons.getIcon("shadow-tr"); //$NON-NLS-1$
+ assert sShadowBottomRight.getImageData().width == SHADOW_SIZE;
+ assert sShadowBottomRight.getImageData().height == SHADOW_SIZE;
+ }
+
+ ImageData bottomLeftData = sShadowBottomLeft.getImageData();
+ ImageData topRightData = sShadowTopRight.getImageData();
+ ImageData bottomData = sShadowBottom.getImageData();
+ ImageData rightData = sShadowRight.getImageData();
+ int blWidth = bottomLeftData.width;
+ int trHeight = topRightData.height;
+ if (width < blWidth) {
+ return;
+ }
+ if (height < trHeight) {
+ return;
+ }
+
+ gc.drawImage(sShadowBottomLeft, x, y + height);
+ gc.drawImage(sShadowBottomRight, x + width, y + height);
+ gc.drawImage(sShadowTopRight, x + width, y);
+ gc.drawImage(sShadowBottom,
+ 0, 0,
+ bottomData.width, bottomData.height,
+ x + bottomLeftData.width, y + height,
+ width - bottomLeftData.width, bottomData.height);
+ gc.drawImage(sShadowRight,
+ 0, 0,
+ rightData.width, rightData.height,
+ x + width, y + topRightData.height,
+ rightData.width, height - topRightData.height);
+ }
+
+ private static Image sShadowBottomLeft;
+ private static Image sShadowBottom;
+ private static Image sShadowBottomRight;
+ private static Image sShadowRight;
+ private static Image sShadowTopRight;
}