/*******************************************************************************
* Copyright (c) 2009 Paul VanderLei, Simon Archer, Jeff McAffer and others. All
* rights reserved. This program and the accompanying materials are made
* available under the terms of the Eclipse Public License v1.0 and Eclipse
* Distribution License v1.0 which accompanies this distribution. The Eclipse
* Public License is available at http://www.eclipse.org/legal/epl-v10.html and
* the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors: Paul VanderLei, Simon Archer, Jeff McAffer - initial API and
* implementation
*******************************************************************************/
package org.eclipse.examples.toast.crust.widgets;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TypedListener;
public class ImageButton extends Canvas implements Listener {
private Image downImage;
private Image upImage;
private Image image;
private Image depressedImage;
private String text;
private boolean selected;
private boolean tempSelected;
public ImageButton(Composite parent, int style) {
super(parent, style);
addListener(SWT.Paint, this);
addListener(SWT.Dispose, this);
addListener(SWT.MouseDown, this);
addListener(SWT.MouseUp, this);
}
public void setImages(Image upImage, Image downImage) {
setImages(upImage, downImage, null);
}
public void setImages(Image upImage, Image downImage, Image depressedImage) {
this.upImage = upImage;
this.downImage = downImage;
this.depressedImage = depressedImage != null ? depressedImage : downImage;
setImage(this.upImage);
}
public void setRegionFromImage() {
Region region = getRegion();
if (region != null)
region.dispose();
region = new Region();
ImageData imageData = image.getImageData();
if (imageData.alphaData != null) {
Rectangle pixel = new Rectangle(0, 0, 1, 1);
for (int y = 0; y < imageData.height; y++) {
for (int x = 0; x < imageData.width; x++)
if (imageData.getAlpha(x, y) == 255) {
pixel.x = imageData.x + x;
pixel.y = imageData.y + y;
region.add(pixel);
}
}
} else {
ImageData mask = imageData.getTransparencyMask();
Rectangle pixel = new Rectangle(0, 0, 1, 1);
for (int y = 0; y < mask.height; y++) {
for (int x = 0; x < mask.width; x++)
if (mask.getPixel(x, y) != 0) {
pixel.x = imageData.x + x;
pixel.y = imageData.y + y;
region.add(pixel);
}
}
}
setRegion(region);
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
redraw();
}
public Point computeSize(int wHint, int hHint, boolean changed) {
int width = 0;
int height = 0;
if (image != null) {
Rectangle bounds = image.getBounds();
width = bounds.width;
height = bounds.height;
}
if (text != null) {
GC gc = new GC(this);
Point extent = gc.stringExtent(text);
gc.dispose();
width = Math.max(width, extent.x);
height = Math.max(height, extent.y);
}
if (wHint != -1)
width = wHint;
if (hHint != -1)
height = hHint;
return new Point(width, height);
}
public void addSelectionListener(SelectionListener listener) {
checkWidget();
if (listener == null)
SWT.error(SWT.ERROR_NULL_ARGUMENT);
TypedListener typedListener = new TypedListener(listener);
addListener(SWT.Selection, typedListener);
addListener(SWT.DefaultSelection, typedListener);
}
public void removeSelectionListener(SelectionListener listener) {
checkWidget();
if (listener == null)
SWT.error(SWT.ERROR_NULL_ARGUMENT);
removeListener(SWT.Selection, listener);
removeListener(SWT.DefaultSelection, listener);
}
public void setSelection(boolean selected) {
this.selected = selected;
setImage(selected ? downImage : upImage);
}
public boolean getSelection() {
return selected;
}
private void paintControl(Event e) {
GC gc = e.gc;
Rectangle size = getBounds();
if (image != null) {
Rectangle iSize = image.getBounds();
int widthOffset = computeOffset(size.width, iSize.width);
int heightOffset = computeOffset(size.height, iSize.height);
gc.drawImage(image, widthOffset, heightOffset);
}
if (text != null) {
Point tSize = gc.textExtent(text);
int widthOffset = computeOffset(size.width, tSize.x);
int heightOffset = computeOffset(size.height, tSize.y);
gc.drawString(text, widthOffset, heightOffset, true);
}
}
private int computeOffset(int i, int j) {
if (j >= i)
return 0;
else
return (i - j) / 2;
}
private void widgetDisposed(Event e) {
Region region = getRegion();
if (region != null)
region.dispose();
}
private void mouseUp(Event e) {
if (!tempSelected)
return;
tempSelected = false;
if ((getStyle() & SWT.TOGGLE) != 0) {
if (selected) {
selected = false;
setImage(upImage);
} else {
selected = true;
setImage(downImage);
}
} else {
setImage(selected ? downImage : upImage);
if ((getStyle() & SWT.RADIO) != 0 && (getParent().getStyle() & SWT.NO_RADIO_GROUP) == 0)
selectRadio();
}
notifyListeners(SWT.Selection, new Event());
}
private void mouseDown(Event e) {
Region r = getRegion();
if (r == null || r.contains(e.x, e.y))
pickImage();
}
private void pickImage() {
if ((getStyle() & SWT.TOGGLE | SWT.CHECK) != 0)
setImage(depressedImage);
else
setImage(selected ? downImage : depressedImage);
tempSelected = true;
}
private void setImage(Image image) {
this.image = image;
redraw();
}
public Image getImage() {
return image;
}
public Image[] getImages() {
return (new Image[] {upImage, downImage, depressedImage});
}
private void selectRadio() {
org.eclipse.swt.widgets.Control children[] = getParent().getChildren();
for (int i = 0; i < children.length; i++)
if (children[i] instanceof ImageButton) {
ImageButton child = (ImageButton) children[i];
if ((this != child) & ((child.getStyle() & SWT.RADIO) != 0))
child.setRadioSelection(false);
}
if ((getStyle() & SWT.PUSH) == 0)
setSelection(true);
}
private void setRadioSelection(boolean value) {
if ((getStyle() & SWT.RADIO) == 0)
return;
if (getSelection() != value) {
setSelection(value);
notifyListeners(SWT.Selection, new Event());
}
}
public void handleEvent(Event event) {
switch (event.type) {
case SWT.Paint :
paintControl(event);
break;
case SWT.MouseUp :
mouseUp(event);
break;
case SWT.MouseDown :
mouseDown(event);
break;
case SWT.Dispose :
widgetDisposed(event);
break;
}
}
}