blob: 3c22a79f35783dd7e88a3c91d35544ac8187db04 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Laurent CARON
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
*******************************************************************************/
package org.mihalis.opal.launcher;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Font;
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;
import org.mihalis.opal.utils.SWTGraphicUtil;
/**
* Instance of this class are a button with text, image and a nice animation
* effect.
*/
class LauncherLabel extends Canvas {
/** The text. */
private String text;
/** The image. */
private Image image;
/** The font. */
private Font font;
/** The Constant GAP. */
private static final int GAP = 12;
/** The draw flags. */
private static int DRAW_FLAGS = SWT.DRAW_MNEMONIC | SWT.DRAW_TAB | SWT.DRAW_TRANSPARENT | SWT.DRAW_DELIMITER;
/** The Constant DEFAULT_MARGIN. */
private static final int DEFAULT_MARGIN = 5;
/** The left margin. */
private int leftMargin = DEFAULT_MARGIN;
/** The top margin. */
private int topMargin = DEFAULT_MARGIN;
/** The right margin. */
private int rightMargin = DEFAULT_MARGIN;
/** The bottom margin. */
private int bottomMargin = DEFAULT_MARGIN;
/** The text size. */
private Point textSize;
/** The Constant MAX_NUMBER_OF_STEPS. */
private static final int MAX_NUMBER_OF_STEPS = 10;
/** The animation step. */
private int animationStep = 0;
/**
* Constructs a new instance of this class given its parent and a style
* value describing its behavior and appearance.
* <p>
* The style value is either one of the style constants defined in class
* <code>SWT</code> which is applicable to instances of 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 <code>SWT</code>
* style constants. The class description lists the style constants that are
* applicable to the class. Style bits are also inherited from superclasses.
* </p>
*
* @param parent a composite control which will be the parent of the new
* instance (cannot be null)
* @param style the style of control to construct
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the parent</li>
* </ul>
*
*/
LauncherLabel(final Composite parent, final int style) {
super(parent, style | SWT.BORDER | SWT.DOUBLE_BUFFERED);
final Font original = super.getFont();
final Font defaultFont = new Font(getDisplay(), original.getFontData()[0].getName(), 18, SWT.BOLD);
this.font = defaultFont;
SWTGraphicUtil.addDisposer(this, defaultFont);
addPaintListener(new PaintListener() {
@Override
public void paintControl(final PaintEvent event) {
onPaint(event);
}
});
}
/**
* Draw the content of the LLabel.
*
* @param event paintevent
*/
private void onPaint(final PaintEvent event) {
final Rectangle rect = getClientArea();
if (rect.width == 0 || rect.height == 0) {
return;
}
final Image bufferImage = new Image(getDisplay(), Math.max(1, rect.width), Math.max(1, rect.height));
final GC gc = new GC(bufferImage);
gc.setForeground(getForeground());
gc.setBackground(getBackground());
gc.fillRectangle(rect);
final Point extent = getTotalSize(this.image.getBounds().width, this.image.getBounds().height);
final int xImage = (rect.width - this.image.getBounds().width) / 2;
final int yImage = (rect.height - extent.y) / 2;
gc.drawImage(this.image, xImage, yImage);
gc.setFont(this.font);
final int xText = (rect.width - this.textSize.x) / 2;
final int yText = yImage + this.image.getBounds().height + GAP - this.textSize.y / 2;
gc.drawString(this.text, xText, yText);
if (this.animationStep != 0) {
final float zoom = 1f + this.animationStep * (Math.max(extent.x, extent.y) - Math.max(this.image.getBounds().width, this.image.getBounds().height)) / MAX_NUMBER_OF_STEPS / 100f;
final int newSizeX = (int) (this.image.getBounds().width * zoom);
final int newSizeY = (int) (this.image.getBounds().height * zoom);
gc.setAntialias(SWT.ON);
gc.setInterpolation(SWT.HIGH);
gc.setAlpha(255 - 255 / MAX_NUMBER_OF_STEPS * this.animationStep);
final Point extentZoomedImage = getTotalSize(newSizeX, newSizeY);
final int xZoomedImage = (rect.width - newSizeX) / 2;
final int yZoomedImage = (rect.height - extentZoomedImage.y) / 2;
gc.drawImage(this.image, 0, 0, this.image.getBounds().width, this.image.getBounds().height, xZoomedImage, yZoomedImage, (int) (this.image.getBounds().width * zoom), (int) (this.image.getBounds().height * zoom));
}
gc.dispose();
event.gc.drawImage(bufferImage, 0, 0);
bufferImage.dispose();
}
/**
* Compute size.
*
* @param wHint the w hint
* @param hHint the h hint
* @param changed the changed
* @return the point
* @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
*/
@Override
public Point computeSize(final int wHint, final int hHint, final boolean changed) {
checkWidget();
final Point e = getTotalSize(this.image.getBounds().width, this.image.getBounds().height);
if (wHint == SWT.DEFAULT) {
e.x += this.leftMargin + this.rightMargin;
} else {
e.x = wHint;
}
if (hHint == SWT.DEFAULT) {
e.y += this.topMargin + this.bottomMargin;
} else {
e.y = hHint;
}
return e;
}
/**
* Compute the size of the content (image + text + gap).
*
* @param imgWidth image width
* @param imgHeight image height
* @return the size of the content
*/
private Point getTotalSize(final int imgWidth, final int imgHeight) {
final Point size = new Point(0, 0);
int textWidth = 0;
int textHeight = 0;
if (this.textSize == null) {
final GC gc = new GC(this);
gc.setFont(this.font);
this.textSize = gc.textExtent(this.text, DRAW_FLAGS);
gc.dispose();
}
textWidth = this.textSize.x;
textHeight = this.textSize.y;
size.x = Math.max(imgWidth, textWidth);
size.y = imgHeight + GAP + textHeight;
return size;
}
/**
* Gets the text.
*
* @return the text
*/
String getText() {
return this.text;
}
/**
* Sets the text.
*
* @param text the text to set
*/
void setText(final String text) {
this.text = text;
}
/**
* Gets the image.
*
* @return the image
*/
Image getImage() {
return this.image;
}
/**
* Sets the image.
*
* @param image the image to set
*/
void setImage(final Image image) {
this.image = image;
}
/**
* Gets the font.
*
* @return the font
*/
@Override
public Font getFont() {
return this.font;
}
/**
* Sets the font.
*
* @param font the font to set
*/
@Override
public void setFont(final Font font) {
this.font = font;
}
/**
* Increment the steps of the animation.
*
* @return true if animation keeps running, false otherwise
*/
boolean incrementAnimation() {
this.animationStep++;
final boolean stopAnimation = this.animationStep > MAX_NUMBER_OF_STEPS;
if (stopAnimation) {
this.animationStep = 0;
}
if (!isDisposed()) {
redraw();
}
return !stopAnimation;
}
/**
* Gets the left margin.
*
* @return the left margin
*/
public int getLeftMargin() {
return this.leftMargin;
}
/**
* Sets the left margin.
*
* @param leftMargin the left margin to set
*/
public void setLeftMargin(final int leftMargin) {
this.leftMargin = leftMargin;
}
/**
* Gets the top margin.
*
* @return the top margin
*/
public int getTopMargin() {
return this.topMargin;
}
/**
* Sets the top margin.
*
* @param topMargin the top margin to set
*/
public void setTopMargin(final int topMargin) {
this.topMargin = topMargin;
}
/**
* Gets the right margin.
*
* @return the right margin
*/
public int getRightMargin() {
return this.rightMargin;
}
/**
* Sets the right margin.
*
* @param rightMargin the right margin to set
*/
public void setRightMargin(final int rightMargin) {
this.rightMargin = rightMargin;
}
/**
* Gets the bottom margin.
*
* @return the bottom margin
*/
public int getBottomMargin() {
return this.bottomMargin;
}
/**
* Sets the bottom margin.
*
* @param bottomMargin the bottom margin to set
*/
public void setBottomMargin(final int bottomMargin) {
this.bottomMargin = bottomMargin;
}
}