| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 |
| * |
| * 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.draw9patch.ui; |
| |
| import com.android.ide.eclipse.adt.AdtPlugin; |
| import com.android.ide.eclipse.adt.internal.editors.draw9patch.graphics.GraphicsUtilities; |
| import com.android.ide.eclipse.adt.internal.editors.draw9patch.graphics.NinePatchedImage; |
| import com.android.ide.eclipse.adt.internal.editors.draw9patch.graphics.NinePatchedImage.Projection; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.PaintEvent; |
| import org.eclipse.swt.events.PaintListener; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.ImageData; |
| import org.eclipse.swt.graphics.PaletteData; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.RGB; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.layout.FillLayout; |
| import org.eclipse.swt.widgets.Canvas; |
| import org.eclipse.swt.widgets.Composite; |
| |
| /** |
| * Preview 9-patched image pane. |
| */ |
| public class StretchesViewer extends Composite { |
| private static final boolean DEBUG = false; |
| |
| private static final int PADDING_COLOR = 0x0000CC; |
| |
| private static final int PADDING_COLOR_ALPHA = 100; |
| |
| private static final PaletteData PADDING_PALLET |
| = new PaletteData(new RGB[] {new RGB(0x00, 0x00, 0xCC)}); |
| |
| private static final String CHECKER_PNG_PATH = "/icons/checker.png"; |
| |
| private Image mBackgroundLayer = null; |
| |
| private final StretchView mHorizontal; |
| private final StretchView mVertical; |
| |
| private final StretchView mBoth; |
| |
| private NinePatchedImage mNinePatchedImage = null; |
| |
| private ImageData mContentAreaImageData = null; |
| |
| private boolean mIsContentAreaShown = false; |
| |
| private Image mContentAreaImage = null; |
| |
| private int mScale = 2; |
| |
| public StretchesViewer(Composite parent, int style) { |
| super(parent, style); |
| |
| mBackgroundLayer = AdtPlugin.getImageDescriptor(CHECKER_PNG_PATH).createImage(); |
| |
| setLayout(new FillLayout(SWT.VERTICAL)); |
| |
| mHorizontal = new StretchView(this, SWT.NULL); |
| mVertical = new StretchView(this, SWT.NULL); |
| mBoth = new StretchView(this, SWT.NULL); |
| } |
| |
| /** |
| * Set show/not show content area. |
| * @param If show, true |
| */ |
| public void setShowContentArea(boolean show) { |
| mIsContentAreaShown = show; |
| redraw(); |
| } |
| |
| private static final boolean equalSize(ImageData image1, ImageData image2) { |
| return (image1.width == image2.width && image1.height == image2.height); |
| } |
| |
| /** |
| * Update preview image. |
| */ |
| public void updatePreview(NinePatchedImage image) { |
| mNinePatchedImage = image; |
| ImageData base = mNinePatchedImage.getImageData(); |
| |
| if (mContentAreaImageData == null |
| || (mContentAreaImageData != null && !equalSize(base, mContentAreaImageData))) { |
| mContentAreaImageData = new ImageData( |
| base.width, |
| base.height, |
| 1, |
| PADDING_PALLET); |
| } else { |
| GraphicsUtilities.clearImageData(mContentAreaImageData); |
| } |
| |
| mHorizontal.setImage(mNinePatchedImage); |
| mVertical.setImage(mNinePatchedImage); |
| mBoth.setImage(mNinePatchedImage); |
| |
| mContentAreaImage = buildContentAreaPreview(); |
| |
| setScale(mScale); |
| } |
| |
| private Image buildContentAreaPreview() { |
| if (mContentAreaImage != null) { |
| mContentAreaImage.dispose(); |
| } |
| |
| Rectangle rect = mNinePatchedImage.getContentArea(); |
| |
| int yLen = rect.y + rect.height; |
| for (int y = rect.y; y < yLen; y++) { |
| int xLen = rect.x + rect.width; |
| for (int x = rect.x; x < xLen; x++) { |
| mContentAreaImageData.setPixel(x, y, PADDING_COLOR); |
| mContentAreaImageData.setAlpha(x, y, PADDING_COLOR_ALPHA); |
| } |
| } |
| return new Image(AdtPlugin.getDisplay(), mContentAreaImageData); |
| } |
| |
| public void setScale(int scale) { |
| if (DEBUG) { |
| System.out.println("scale = " + scale); |
| } |
| |
| mScale = scale; |
| int imageWidth = mNinePatchedImage.getWidth(); |
| int imageHeight = mNinePatchedImage.getHeight(); |
| |
| mHorizontal.setSize(imageWidth * scale, imageHeight); |
| mVertical.setSize(imageWidth, imageHeight * scale); |
| mBoth.setSize(imageWidth * scale, imageHeight * scale); |
| |
| redraw(); |
| } |
| |
| @Override |
| public void dispose() { |
| mBackgroundLayer.dispose(); |
| super.dispose(); |
| } |
| |
| private class StretchView extends Canvas implements PaintListener { |
| |
| private final Point mSize = new Point(0, 0); |
| private final Rectangle mPadding = new Rectangle(0, 0, 0, 0); |
| private Projection[][] mProjection = null; |
| |
| public StretchView(Composite parent, int style) { |
| super(parent, style); |
| addPaintListener(this); |
| } |
| |
| private void setImage(NinePatchedImage image) { |
| setSize(image.getWidth(), image.getHeight()); |
| } |
| |
| @Override |
| public void setSize(int width, int heigh) { |
| mSize.x = width; |
| mSize.y = heigh; |
| mProjection = mNinePatchedImage.getProjections(mSize.x, mSize.y, mProjection); |
| } |
| |
| private synchronized void calcPaddings(int width, int height) { |
| Point canvasSize = getSize(); |
| |
| mPadding.x = (canvasSize.x - width) / 2; |
| mPadding.y = (canvasSize.y - height) / 2; |
| |
| mPadding.width = width; |
| mPadding.height = height; |
| } |
| |
| @Override |
| public void paintControl(PaintEvent pe) { |
| if (mNinePatchedImage == null || mProjection == null) { |
| return; |
| } |
| |
| Point size = getSize(); |
| |
| // relative scaling |
| float ratio = 1.0f; |
| float wRatio = ((float) size.x / mSize.x); |
| ratio = Math.min(wRatio, ratio); |
| float hRatio = ((float) size.y / mSize.y); |
| ratio = Math.min(hRatio, ratio); |
| |
| int width = Math.round(mSize.x * ratio); |
| int height = Math.round(mSize.y * ratio); |
| |
| calcPaddings(width, height); |
| |
| Rectangle dest = new Rectangle(0, 0, 0, 0); |
| |
| GC gc = pe.gc; |
| |
| int backgroundLayerWidth = mBackgroundLayer.getImageData().width; |
| int backgroundLayerHeight = mBackgroundLayer.getImageData().height; |
| |
| int yCount = size.y / backgroundLayerHeight |
| + ((size.y % backgroundLayerHeight) > 0 ? 1 : 0); |
| int xCount = size.x / backgroundLayerWidth |
| + ((size.x % backgroundLayerWidth) > 0 ? 1 : 0); |
| |
| // draw background layer |
| for (int y = 0; y < yCount; y++) { |
| for (int x = 0; x < xCount; x++) { |
| gc.drawImage(mBackgroundLayer, |
| x * backgroundLayerWidth, |
| y * backgroundLayerHeight); |
| } |
| } |
| |
| // draw the border line |
| gc.setAlpha(0x88); |
| gc.drawRectangle(0, 0, size.x, size.y); |
| gc.setAlpha(0xFF); |
| |
| int yLen = mProjection.length; |
| int xLen = mProjection[0].length; |
| for (int yPos = 0; yPos < yLen; yPos++) { |
| for (int xPos = 0; xPos < xLen; xPos++) { |
| Projection p = mProjection[yPos][xPos]; |
| |
| // consider the scale |
| dest.x = (int) Math.ceil(p.dest.x * ratio); |
| dest.y = (int) Math.ceil(p.dest.y * ratio); |
| dest.width = (int) Math.ceil(p.dest.width * ratio); |
| dest.height = (int) Math.ceil(p.dest.height * ratio); |
| |
| gc.drawImage(mNinePatchedImage.getImage(), p.src.x, p.src.y, |
| p.src.width, p.src.height, |
| (mPadding.x + dest.x), (mPadding.y + dest.y), |
| dest.width, dest.height); |
| |
| if (mIsContentAreaShown) { |
| gc.drawImage(mContentAreaImage, p.src.x, p.src.y, |
| p.src.width, p.src.height, |
| (mPadding.x + dest.x), (mPadding.y + dest.y), |
| dest.width, dest.height); |
| } |
| } |
| } |
| } |
| } |
| } |