blob: 4447eebd2359919bb963c9c5bb995f5f335f5660 [file] [log] [blame]
/*
* Copyright (C) 2011 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.NonNull;
import com.android.annotations.Nullable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
/**
* An ImageControl which simply renders an image, with optional margins and tooltips. This
* is useful since a {@link CLabel}, even without text, will hide the image when there is
* not enough room to fully fit it.
* <p>
* The image is always rendered left and top aligned.
*/
public class ImageControl extends Canvas implements MouseTrackListener {
private Image mImage;
private int mLeftMargin;
private int mTopMargin;
private int mRightMargin;
private int mBottomMargin;
private boolean mDisposeImage = true;
private boolean mMouseIn;
private Color mHoverColor;
private float mScale = 1.0f;
/**
* Creates an ImageControl rendering the given image, which will be disposed when this
* control is disposed (unless the {@link #setDisposeImage} method is called to turn
* off auto dispose).
*
* @param parent the parent to add the image control to
* @param style the SWT style to use
* @param image the image to be rendered, which must not be null and should be unique
* for this image control since it will be disposed by this control when
* the control is disposed (unless the {@link #setDisposeImage} method is
* called to turn off auto dispose)
*/
public ImageControl(@NonNull Composite parent, int style, @Nullable Image image) {
super(parent, style | SWT.NO_FOCUS | SWT.DOUBLE_BUFFERED);
mImage = image;
addPaintListener(new PaintListener() {
@Override
public void paintControl(PaintEvent event) {
onPaint(event);
}
});
}
@Nullable
public Image getImage() {
return mImage;
}
public void setImage(@Nullable Image image) {
if (mDisposeImage && mImage != null) {
mImage.dispose();
}
mImage = image;
redraw();
}
public void fitToWidth(int width) {
if (mImage == null) {
return;
}
Rectangle imageRect = mImage.getBounds();
int imageWidth = imageRect.width;
if (imageWidth <= width) {
mScale = 1.0f;
return;
}
mScale = width / (float) imageWidth;
redraw();
}
public void setScale(float scale) {
mScale = scale;
}
public float getScale() {
return mScale;
}
public void setHoverColor(@Nullable Color hoverColor) {
if (mHoverColor != null) {
removeMouseTrackListener(this);
}
mHoverColor = hoverColor;
if (hoverColor != null) {
addMouseTrackListener(this);
}
}
@Nullable
public Color getHoverColor() {
return mHoverColor;
}
@Override
public void dispose() {
super.dispose();
if (mDisposeImage && mImage != null && !mImage.isDisposed()) {
mImage.dispose();
}
mImage = null;
}
public void setDisposeImage(boolean disposeImage) {
mDisposeImage = disposeImage;
}
public boolean getDisposeImage() {
return mDisposeImage;
}
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
checkWidget();
Point e = new Point(0, 0);
if (mImage != null) {
Rectangle r = mImage.getBounds();
if (mScale != 1.0f) {
e.x += mScale * r.width;
e.y += mScale * r.height;
} else {
e.x += r.width;
e.y += r.height;
}
}
if (wHint == SWT.DEFAULT) {
e.x += mLeftMargin + mRightMargin;
} else {
e.x = wHint;
}
if (hHint == SWT.DEFAULT) {
e.y += mTopMargin + mBottomMargin;
} else {
e.y = hHint;
}
return e;
}
private void onPaint(PaintEvent event) {
Rectangle rect = getClientArea();
if (mImage == null || rect.width == 0 || rect.height == 0) {
return;
}
GC gc = event.gc;
Rectangle imageRect = mImage.getBounds();
int imageHeight = imageRect.height;
int imageWidth = imageRect.width;
int destWidth = imageWidth;
int destHeight = imageHeight;
int oldGcAlias = gc.getAntialias();
int oldGcInterpolation = gc.getInterpolation();
if (mScale != 1.0f) {
destWidth = (int) (mScale * destWidth);
destHeight = (int) (mScale * destHeight);
gc.setAntialias(SWT.ON);
gc.setInterpolation(SWT.HIGH);
}
gc.drawImage(mImage, 0, 0, imageWidth, imageHeight, rect.x + mLeftMargin, rect.y
+ mTopMargin, destWidth, destHeight);
gc.setAntialias(oldGcAlias);
gc.setInterpolation(oldGcInterpolation);
if (mHoverColor != null && mMouseIn) {
gc.setAlpha(60);
gc.setBackground(mHoverColor);
gc.setLineWidth(1);
gc.fillRectangle(0, 0, destWidth, destHeight);
}
}
public void setMargins(int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
checkWidget();
mLeftMargin = Math.max(0, leftMargin);
mTopMargin = Math.max(0, topMargin);
mRightMargin = Math.max(0, rightMargin);
mBottomMargin = Math.max(0, bottomMargin);
redraw();
}
// ---- Implements MouseTrackListener ----
@Override
public void mouseEnter(MouseEvent e) {
mMouseIn = true;
if (mHoverColor != null) {
redraw();
}
}
@Override
public void mouseExit(MouseEvent e) {
mMouseIn = false;
if (mHoverColor != null) {
redraw();
}
}
@Override
public void mouseHover(MouseEvent e) {
}
}