/* ******************************************************************************
* Copyright (c) 2006-2015 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.ui.viewers;
import org.eclipse.swt.SWT;
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.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
/**
* Instances of this class are controls that draws an image as its content.
* <dl>
* <dt><b>Styles:</b></dt>
* <dd>(none)</dd>
* <dt><b>Events:</b></dt>
* <dd>(none)</dd>
* </dl>
*
* @author Frank Shaka
* @since 3.6.0
*/
public class ImageLabel extends Composite {
/**
* Does not scale image.
*/
public static final int SCALE_NONE = 0;
/**
* Scales the image so that the whole image can be shown in the control.
*/
public static final int SCALE_TO_FIT = 1 << 0;
/**
* Does not scale image when it is needed to expand the image.
* <p>
* Only valid when SCALE_TO_FIT is specified.
* </p>
*/
public static final int SCALE_NO_EXPAND = 1 << 10;
private Image image = null;
private int hAlignment = SWT.CENTER;
private int vAlignment = SWT.CENTER;
private int scaleHint = SCALE_NONE;
public ImageLabel(Composite parent, int style) {
super(parent, style);
addListener(SWT.Paint, new Listener() {
public void handleEvent(Event event) {
onPaint(event);
}
});
}
private void onPaint(Event event) {
paintImageLabel(event.gc);
}
protected void paintImageLabel(GC gc) {
if (image == null)
return;
Rectangle imgArea = image.getBounds();
if (imgArea.width == 0 || imgArea.height == 0)
return;
Rectangle target = computePaintArea(imgArea, getClientArea());
gc.setAntialias(SWT.ON);
gc.drawImage(image, imgArea.x, imgArea.y, imgArea.width, imgArea.height,
target.x, target.y, target.width, target.height);
}
protected Rectangle computePaintArea(Rectangle imgArea,
Rectangle clientArea) {
Rectangle target = new Rectangle(clientArea.x, clientArea.y,
imgArea.width, imgArea.height);
if ((scaleHint & SCALE_TO_FIT) != 0) {
// Let scales be
// hScale = ctlSize.width / imgSize.width
// vScale = ctlSize.height / imgSize.height
// We will choose the control height as the target height if the
// vScale is smaller than the hScale, so we get the inequation:
// ctlSize.width / imgSize.width > ctlSize.height / imgSize.height
// To avoid float point calculations, we transform the above
// inequation into an equivalent one:
if (clientArea.width * imgArea.height > clientArea.height
* imgArea.width) {
// use control height as target height, calculate target width
target.height = clientArea.height;
target.width = imgArea.width * clientArea.height
/ imgArea.height;
} else {
// use control width as target width, calculate target height
target.width = clientArea.width;
target.height = imgArea.height * clientArea.width
/ imgArea.width;
}
if ((scaleHint & SCALE_NO_EXPAND) != 0
&& (target.width > imgArea.width
|| target.height > imgArea.height)) {
target.width = imgArea.width;
target.height = imgArea.height;
}
}
if ((hAlignment & SWT.CENTER) != 0) {
target.x += (clientArea.width - target.width) / 2;
} else if ((hAlignment & SWT.TRAIL) != 0) {
target.x += clientArea.width - target.width;
}
if ((vAlignment & SWT.CENTER) != 0) {
target.y += (clientArea.height - target.height) / 2;
} else if ((vAlignment & SWT.TRAIL) != 0) {
target.y += clientArea.height - target.height;
}
return target;
}
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
Point size;
if (wHint != SWT.DEFAULT && hHint != SWT.DEFAULT) {
size = new Point(wHint, hHint);
} else if (image == null) {
size = new Point(0, 0);
} else {
Rectangle b = image.getBounds();
if (b.width == 0 || b.height == 0) {
size = new Point(0, 0);
} else {
size = new Point(b.width, b.height);
if (wHint != SWT.DEFAULT) {
size.x = wHint;
size.y = b.height * wHint / b.width;
} else if (hHint != SWT.DEFAULT) {
size.y = hHint;
size.x = b.width * hHint / b.height;
}
}
}
Rectangle trimmed = computeTrim(0, 0, size.x, size.y);
return new Point(trimmed.width, trimmed.height);
}
public Image getImage() {
return image;
}
public void setImage(Image image) {
checkWidget();
if (image == this.image)
return;
this.image = image;
redraw();
}
public int getHorizontalAlignment() {
return hAlignment;
}
/**
*
* @param alignment
* one of SWT.LEAD, SWT.CENTER, SWT.TRAIL
*/
public void setHorizontalAlignment(int alignment) {
checkWidget();
if (alignment == this.hAlignment)
return;
this.hAlignment = alignment;
redraw();
}
public int getVerticalAlignment() {
return vAlignment;
}
public void setVerticalAlignment(int alignment) {
checkWidget();
if (alignment == this.vAlignment)
return;
this.vAlignment = alignment;
redraw();
}
public int getScaleHint() {
return scaleHint;
}
/**
* Specifies how to scale the image to fit in the control.
*
* <p>
* The hint value is either one of the <code>SCALE_*</code> hint constants
* defined in this class, or must be built by <em>bitwise OR</em>'ing
* together (that is, using the <code>int</code> "|" operator) two or more
* of those hint constants.
* </p>
*
* @param hint
* one of SCALE_NONE, SCALE_TO_FIT, SCALE_TO_FILL,
* SCALE_TO_EXPAND, SCALE_TO_SHRINK
*/
public void setScaleHint(int hint) {
checkWidget();
if ((hint & SCALE_TO_FIT) == 0) {
hint = SCALE_NONE;
}
if (hint == this.scaleHint)
return;
this.scaleHint = hint;
redraw();
}
}