blob: 353312c85a95aa0a22a8e16e90872efd4db3b539 [file] [log] [blame]
/*
* 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);
}
}
}
}
}
}