diff options
author | Tor Norbye <tnorbye@google.com> | 2012-07-30 07:03:03 -0700 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2012-07-31 09:38:25 -0700 |
commit | 68d4aa68f412049e12c644b32f12f4219b9f49d5 (patch) | |
tree | 22af60b1e580f1ba1f88afad4422f5783e85c1b9 /eclipse/plugins/com.android.ide.eclipse.adt | |
parent | a7d1df4109bbde358b542931864148ea97eca917 (diff) | |
download | sdk-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')
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 Binary files differnew file mode 100644 index 0000000..68f4f4b --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-b.png 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 Binary files differnew file mode 100644 index 0000000..ee7dbe8 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-bl.png 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 Binary files differnew file mode 100644 index 0000000..c45ad77 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-br.png 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 Binary files differnew file mode 100644 index 0000000..4af7a33 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-r.png 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 Binary files differnew file mode 100644 index 0000000..1fd0c77 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/shadow-tr.png 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; } |