blob: bf6b0f8a3e96bcb4c95b8bb4f661f4e742af6f48 [file] [log] [blame]
/*
* Copyright (c) 2014, 2015 Eike Stepper (Berlin, Germany) and others.
* 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:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.oomph.internal.ui;
import org.eclipse.oomph.ui.UIUtil;
import org.eclipse.oomph.util.IOUtil;
import org.eclipse.emf.common.util.URI;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Drawable;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Widget;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Ed Merks
*/
public final class AccessUtil
{
private static final String DATA_KEY = "oomph.access.key";
public static void setKey(Widget widget, Object key)
{
widget.setData(DATA_KEY, key);
widget.setData("org.eclipse.swtbot.widget.key", key);
}
public static Image capture(Control control)
{
if (control instanceof Shell)
{
Display display = control.getDisplay();
Shell shell = (Shell)control;
Rectangle bounds = shell.getBounds();
bounds.x -= 12;
bounds.y -= 11;
bounds.width += 28;
bounds.height += 28;
return captureDrawable(display, display, bounds);
}
else if (control instanceof Button)
{
Point size = control.getSize();
Rectangle bounds = (control.getStyle() & SWT.CHECK) != 0 ? new Rectangle(0, 2, size.x, size.y - 4) : new Rectangle(0, 1, size.x, size.y - 2);
return capture(control, bounds);
}
else
{
Point size = control.getSize();
Rectangle bounds = new Rectangle(0, 0, size.x, size.y);
return capture(control, bounds);
}
}
public static Image capture(Display display, Rectangle bounds)
{
return captureDrawable(display, display, bounds);
}
public static Image capture(Control control, Rectangle bounds)
{
return captureDrawable(control.getDisplay(), control, bounds);
}
private static Image captureDrawable(Device device, Drawable drawable, Rectangle bounds)
{
GC gc = new GC(drawable);
final Image image = new Image(device, bounds.width, bounds.height);
gc.copyArea(image, bounds.x, bounds.y);
gc.dispose();
return image;
}
public static void save(File file, Control control) throws IOException
{
Point size = control.getSize();
save(file, control, new Rectangle(0, 0, size.x, size.y));
}
public static void save(File file, Control control, Rectangle bounds) throws IOException
{
OutputStream out = null;
Image image = null;
try
{
out = new FileOutputStream(file);
image = capture(control, bounds);
save(out, image, getImageType(URI.createURI(file.getName()).fileExtension()), image.getBounds());
}
finally
{
IOUtil.close(out);
if (image != null)
{
image.dispose();
}
}
}
public static void save(OutputStream out, final Image image, int type) throws IOException
{
final ImageData imageData = image.getImageData();
final Rectangle bounds = getBounds(imageData);
ImageData effectiveImageData = imageData;
if (bounds.x != 0 || bounds.y != 0 || bounds.width != imageData.width || bounds.height != imageData.height)
{
effectiveImageData = new WorkUnit<ImageData, IOException>(IOException.class)
{
@Override
protected ImageData doExecute() throws IOException
{
Image clippedImage = new Image(image.getDevice(), bounds.width, bounds.height);
GC gc = new GC(clippedImage);
gc.setBackground(image.getDevice().getSystemColor(SWT.COLOR_WHITE));
gc.setForeground(image.getDevice().getSystemColor(SWT.COLOR_WHITE));
gc.drawRectangle(0, 0, bounds.width, bounds.height);
gc.drawImage(image, bounds.x, bounds.y, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height);
gc.dispose();
ImageData result = clippedImage.getImageData();
clippedImage.dispose();
return result;
}
}.execute();
}
save(out, effectiveImageData, type, bounds);
}
public static void save(OutputStream out, final Image image, int type, Rectangle bounds) throws IOException
{
save(out, image.getImageData(), type, bounds);
}
public static void save(OutputStream out, ImageData imageData, int type) throws IOException
{
save(out, imageData, type, getBounds(imageData));
}
public static void save(OutputStream out, ImageData imageData, int type, Rectangle bounds) throws IOException
{
ImageLoader imageLoader = new ImageLoader();
imageLoader.data = new ImageData[] { imageData };
imageLoader.save(out, type);
}
public static int getImageType(String fileExtension)
{
if ("jpg".equalsIgnoreCase(fileExtension) || "jpeg".equalsIgnoreCase(fileExtension))
{
return SWT.IMAGE_JPEG;
}
if ("ico".equalsIgnoreCase(fileExtension))
{
return SWT.IMAGE_ICO;
}
if ("bmp".equalsIgnoreCase(fileExtension))
{
return SWT.IMAGE_BMP;
}
if ("gif".equalsIgnoreCase(fileExtension))
{
return SWT.IMAGE_GIF;
}
if ("tiff".equalsIgnoreCase(fileExtension))
{
return SWT.IMAGE_TIFF;
}
return SWT.IMAGE_PNG;
}
private static Rectangle getBounds(ImageData imageData)
{
int left = imageData.width / 2;
int right = imageData.width - left;
int top = imageData.height / 2;
int bottom = imageData.height - top;
int type = imageData.getTransparencyType();
if (type == SWT.TRANSPARENCY_ALPHA)
{
for (int i = 0; i < imageData.height; ++i)
{
for (int j = 0; j < imageData.width; ++j)
{
int alpha = imageData.getAlpha(j, i);
boolean transparent = alpha < 10 ? true : false;
if (!transparent)
{
left = Math.min(left, j);
right = Math.max(right, j);
top = Math.min(top, i);
bottom = Math.max(bottom, i);
}
System.err.print(transparent ? "0" : "1");
}
System.err.println();
}
}
else if (type == SWT.TRANSPARENCY_MASK || type == SWT.TRANSPARENCY_PIXEL)
{
ImageData transparencyMask = imageData.getTransparencyMask();
for (int i = 0; i < transparencyMask.height; ++i)
{
for (int j = 0; j < transparencyMask.width; ++j)
{
boolean transparent = transparencyMask.getPixel(j, i) == 0 ? true : false;
if (!transparent)
{
left = Math.min(left, j);
right = Math.max(right, j);
top = Math.min(top, i);
bottom = Math.max(bottom, i);
}
System.err.print(transparent ? "0" : "1");
}
System.err.println();
}
}
else
{
return new Rectangle(0, 0, imageData.width, imageData.height);
}
return new Rectangle(left, top, right - left + 1, bottom - top + 1);
}
public static void busyWait(int milliseconds)
{
busyWait(milliseconds, null);
}
public static void busyWait(final int milliseconds, final Runnable runnable)
{
final Display display = UIUtil.getDisplay();
final AtomicBoolean done = new AtomicBoolean();
new Thread()
{
@Override
public void run()
{
try
{
// Block on the runnable, if there is one.
if (runnable != null)
{
runnable.run();
}
// Wait 2 more seconds.
UIUtil.asyncExec(new Runnable()
{
public void run()
{
UIUtil.timerExec(milliseconds, new Runnable()
{
public void run()
{
// Ensure that the sleeping display loop wakes up.
done.set(true);
}
});
}
});
}
catch (Exception ex)
{
// Ignore
}
}
}.start();
while (!display.isDisposed() && !done.get())
{
if (!display.readAndDispatch())
{
display.sleep();
}
}
}
public static Object getKey(Widget widget)
{
return widget.getData(DATA_KEY);
}
@SuppressWarnings("unchecked")
public static <T extends Widget> T getWidget(Widget widget, Object key)
{
Object data = getKey(widget);
if (key.equals(data))
{
return (T)widget;
}
if (widget instanceof Composite)
{
Composite composite = (Composite)widget;
for (Control control : composite.getChildren())
{
T result = getWidget(control, key);
if (result != null)
{
return result;
}
}
}
if (widget instanceof ToolBar)
{
ToolBar toolBar = (ToolBar)widget;
for (ToolItem toolItem : toolBar.getItems())
{
T result = getWidget(toolItem, key);
if (result != null)
{
return result;
}
}
}
return null;
}
private AccessUtil()
{
}
}