| /* |
| * 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.ui; |
| |
| import org.eclipse.oomph.internal.ui.UIPlugin; |
| import org.eclipse.oomph.util.ReflectUtil; |
| |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.dialogs.ProgressMonitorDialog; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.SWTError; |
| import org.eclipse.swt.SWTException; |
| import org.eclipse.swt.browser.Browser; |
| import org.eclipse.swt.custom.CCombo; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.ImageData; |
| import org.eclipse.swt.graphics.PaletteData; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.graphics.Resource; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Text; |
| import org.eclipse.swt.widgets.Widget; |
| import org.eclipse.ui.IWorkbench; |
| import org.eclipse.ui.IWorkbenchWindow; |
| import org.eclipse.ui.PlatformUI; |
| |
| import javax.swing.text.html.HTMLEditorKit; |
| import javax.swing.text.html.parser.ParserDelegator; |
| |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.lang.reflect.InvocationTargetException; |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public final class UIUtil |
| { |
| public static final IWorkbench WORKBENCH; |
| |
| private static Image errorImage; |
| |
| private static Image warningImage; |
| |
| private static Image infoImage; |
| |
| private static Boolean browserAvailable; |
| |
| static |
| { |
| IWorkbench workbench = null; |
| |
| try |
| { |
| workbench = PlatformUI.getWorkbench(); |
| } |
| catch (Throwable ex) |
| { |
| // Workbench has not been created. |
| } |
| |
| WORKBENCH = workbench; |
| } |
| |
| private UIUtil() |
| { |
| } |
| |
| public static Display getDisplay() |
| { |
| Display display = Display.getCurrent(); |
| if (display == null) |
| { |
| try |
| { |
| display = PlatformUI.getWorkbench().getDisplay(); |
| } |
| catch (Throwable ignore) |
| { |
| //$FALL-THROUGH$ |
| } |
| } |
| |
| if (display == null) |
| { |
| display = Display.getDefault(); |
| } |
| |
| if (display == null) |
| { |
| display = new Display(); |
| } |
| |
| return display; |
| } |
| |
| public static Shell getShell() |
| { |
| final Shell[] shell = { null }; |
| |
| final Display display = getDisplay(); |
| display.syncExec(new Runnable() |
| { |
| public void run() |
| { |
| shell[0] = display.getActiveShell(); |
| |
| if (shell[0] == null) |
| { |
| try |
| { |
| IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); |
| if (window == null) |
| { |
| IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows(); |
| if (windows.length != 0) |
| { |
| window = windows[0]; |
| } |
| } |
| |
| if (window != null) |
| { |
| shell[0] = window.getShell(); |
| } |
| } |
| catch (Throwable ignore) |
| { |
| //$FALL-THROUGH$ |
| } |
| } |
| |
| if (shell[0] == null) |
| { |
| Shell[] shells = display.getShells(); |
| if (shells.length > 0) |
| { |
| shell[0] = shells[0]; |
| } |
| } |
| } |
| }); |
| |
| return shell[0]; |
| } |
| |
| public static synchronized boolean isBrowserAvailable() |
| { |
| if (browserAvailable == null) |
| { |
| syncExec(new Runnable() |
| { |
| public void run() |
| { |
| Shell shell = null; |
| |
| try |
| { |
| shell = new Shell(); |
| new Browser(shell, SWT.NONE); |
| browserAvailable = true; |
| } |
| catch (SWTError ex) |
| { |
| browserAvailable = false; |
| } |
| finally |
| { |
| try |
| { |
| shell.dispose(); |
| } |
| catch (Exception ex) |
| { |
| // Ignore. |
| } |
| } |
| } |
| }); |
| } |
| |
| return browserAvailable; |
| } |
| |
| /** |
| * Checks if the given {@link Control} is a child of the given |
| * parent. |
| * |
| * @param parent The parent, not <code>null</code>. |
| * @param controlToCheck The control to check, not <code>null</code>. |
| * |
| * @return <code>true</code> if the given control is a child of the given |
| * parent, <code>false</code> otherwise. |
| */ |
| public static boolean isParent(Composite parent, Control controlToCheck) |
| { |
| if (parent == null || controlToCheck == null) |
| { |
| throw new IllegalArgumentException("Neither parent nor controlToCheck must be null"); |
| } |
| |
| if (controlToCheck == parent) |
| { |
| return true; |
| } |
| |
| Composite tmpParent = controlToCheck.getParent(); |
| |
| while (tmpParent != parent && tmpParent != null) |
| { |
| tmpParent = tmpParent.getParent(); |
| } |
| |
| return tmpParent == parent; |
| } |
| |
| public static GridLayout createGridLayout(int numColumns) |
| { |
| GridLayout layout = new GridLayout(numColumns, false); |
| layout.marginWidth = 0; |
| layout.marginHeight = 0; |
| return layout; |
| } |
| |
| public static GridData applyGridData(Control control) |
| { |
| GridData data = new GridData(); |
| data.grabExcessHorizontalSpace = true; |
| data.horizontalAlignment = GridData.FILL; |
| control.setLayoutData(data); |
| return data; |
| } |
| |
| public static GridData grabVertical(GridData data) |
| { |
| data.grabExcessVerticalSpace = true; |
| data.verticalAlignment = GridData.FILL; |
| return data; |
| } |
| |
| public static void clearTextSelection(Object control) |
| { |
| Text text = findTextControl(control); |
| if (text != null) |
| { |
| text.clearSelection(); |
| } |
| } |
| |
| public static void setSelectionToEnd(Widget control) |
| { |
| Text text = findTextControl(control); |
| if (text != null) |
| { |
| String content = text.getText(); |
| text.setSelection(content.length() + 1); |
| } |
| } |
| |
| public static void setSelectionTo(Widget control, Point selection) |
| { |
| Text text = findTextControl(control); |
| if (text != null) |
| { |
| text.setSelection(selection); |
| } |
| } |
| |
| public static void selectAllText(Widget control) |
| { |
| Text text = findTextControl(control); |
| if (text != null) |
| { |
| text.selectAll(); |
| } |
| } |
| |
| private static Text findTextControl(Object control) |
| { |
| if (control instanceof Viewer) |
| { |
| control = ((Viewer)control).getControl(); |
| } |
| |
| if (control instanceof CCombo) |
| { |
| CCombo combo = (CCombo)control; |
| |
| try |
| { |
| control = ReflectUtil.getValue("text", combo); |
| } |
| catch (Throwable ex) |
| { |
| //$FALL-THROUGH$ |
| } |
| } |
| |
| if (control instanceof Text) |
| { |
| return (Text)control; |
| } |
| |
| return null; |
| } |
| |
| public static void runInProgressDialog(Shell shell, IRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException |
| { |
| ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell) |
| { |
| @Override |
| protected Point getInitialSize() |
| { |
| Point calculatedSize = super.getInitialSize(); |
| if (calculatedSize.x < 800) |
| { |
| calculatedSize.x = 800; |
| } |
| |
| return calculatedSize; |
| } |
| }; |
| |
| try |
| { |
| dialog.run(true, true, runnable); |
| } |
| catch (OperationCanceledException ex) |
| { |
| // Ignore. |
| } |
| catch (InvocationTargetException ex) |
| { |
| if (!(ex.getCause() instanceof OperationCanceledException)) |
| { |
| throw ex; |
| } |
| } |
| } |
| |
| public static void handleException(Throwable ex) |
| { |
| UIPlugin.INSTANCE.log(ex); |
| ErrorDialog.open(ex); |
| } |
| |
| public static Color getEclipseThemeColor() |
| { |
| return UIPlugin.getColor(44, 34, 85); |
| } |
| |
| /** |
| * Extracts all sprites from the given textureatlas. |
| * |
| * @param textureAtlas The input texture atlas. |
| * @param countX The number of sprites in horizontal axis. |
| * @param countY The number of sprites in vertical axis. |
| * |
| * @return An array containing the countX * countY sprites. |
| */ |
| public static Image[] extractSprites(Image textureAtlas, int countX, int countY) |
| { |
| Rectangle atlasBounds = textureAtlas.getBounds(); |
| int width = atlasBounds.width / countX; |
| int height = atlasBounds.height / countY; |
| |
| Image[] sprites = new Image[countX * countY]; |
| for (int y = 0; y < countY; y++) |
| { |
| for (int x = 0; x < countX; x++) |
| { |
| sprites[countX * y + x] = UIUtil.extractSprite(textureAtlas, x * width, y * width, width, height); |
| } |
| } |
| |
| return sprites; |
| } |
| |
| /** |
| * Extracts a single sprite from the given texture atlas. |
| * <br> |
| * <br> |
| * <b>Important:</b> the caller is responsible for disposing the created image. |
| * |
| * @param textureAtlas The input texture atlas. |
| * @param x The x coordinate of the target sprite. |
| * @param y The y coordinate of the target sprite. |
| * @param width The width of the target sprite. |
| * @param height The height of the target sprite. |
| * |
| * @return A new image with the extracted sprite. |
| */ |
| public static Image extractSprite(Image textureAtlas, int x, int y, int width, int height) |
| { |
| ImageData textureAtlasData = textureAtlas.getImageData(); |
| PaletteData textureAtlasPaletteData = textureAtlasData.palette; |
| |
| ImageData spriteImageData = new ImageData(width, height, textureAtlasData.depth, |
| new PaletteData(textureAtlasPaletteData.redMask, textureAtlasPaletteData.greenMask, textureAtlasPaletteData.blueMask)); |
| |
| int[] pixels = new int[width * height]; |
| byte[] alphas = new byte[width * height]; |
| |
| for (int scanline = 0; scanline < height; scanline++) |
| { |
| int yOffset = y + scanline; |
| textureAtlasData.getPixels(x, yOffset, width, pixels, scanline * width); |
| textureAtlasData.getAlphas(x, yOffset, width, alphas, scanline * width); |
| } |
| |
| spriteImageData.setPixels(0, 0, pixels.length, pixels, 0); |
| spriteImageData.setAlphas(0, 0, alphas.length, alphas, 0); |
| |
| return new Image(getDisplay(), spriteImageData); |
| } |
| |
| public static Image getStatusImage(int severity) |
| { |
| if (severity == IStatus.ERROR) |
| { |
| if (errorImage == null) |
| { |
| errorImage = UIPlugin.INSTANCE.getSWTImage("error"); |
| } |
| |
| return errorImage; |
| } |
| |
| if (severity == IStatus.WARNING) |
| { |
| if (warningImage == null) |
| { |
| warningImage = UIPlugin.INSTANCE.getSWTImage("warning"); |
| } |
| |
| return warningImage; |
| } |
| |
| if (infoImage == null) |
| { |
| infoImage = UIPlugin.INSTANCE.getSWTImage("info"); |
| } |
| |
| return infoImage; |
| } |
| |
| public static void exec(Display display, boolean async, Runnable runnable) |
| { |
| if (async) |
| { |
| asyncExec(display, runnable); |
| } |
| else |
| { |
| syncExec(display, runnable); |
| } |
| } |
| |
| public static void asyncExec(Runnable runnable) |
| { |
| final Display display = getDisplay(); |
| if (display != null) |
| { |
| asyncExec(display, runnable); |
| } |
| } |
| |
| public static void asyncExec(final Control control, final Runnable runnable) |
| { |
| try |
| { |
| if (control.isDisposed()) |
| { |
| return; |
| } |
| |
| control.getDisplay().asyncExec(new Runnable() |
| { |
| public void run() |
| { |
| if (!control.isDisposed()) |
| { |
| runnable.run(); |
| } |
| } |
| }); |
| } |
| catch (SWTException ex) |
| { |
| if (ex.code != SWT.ERROR_WIDGET_DISPOSED) |
| { |
| throw ex; |
| } |
| |
| //$FALL-THROUGH$ |
| } |
| } |
| |
| public static void asyncExec(final Display display, final Runnable runnable) |
| { |
| try |
| { |
| if (display.isDisposed()) |
| { |
| return; |
| } |
| |
| display.asyncExec(new Runnable() |
| { |
| public void run() |
| { |
| if (display.isDisposed()) |
| { |
| return; |
| } |
| |
| try |
| { |
| runnable.run(); |
| } |
| catch (SWTException ex) |
| { |
| if (ex.code != SWT.ERROR_WIDGET_DISPOSED) |
| { |
| throw ex; |
| } |
| |
| //$FALL-THROUGH$ |
| } |
| } |
| }); |
| } |
| catch (SWTException ex) |
| { |
| if (ex.code != SWT.ERROR_WIDGET_DISPOSED) |
| { |
| throw ex; |
| } |
| |
| //$FALL-THROUGH$ |
| } |
| } |
| |
| public static void syncExec(final Runnable runnable) |
| { |
| final Display display = getDisplay(); |
| if (Display.getCurrent() == display || display == null) |
| { |
| runnable.run(); |
| } |
| else |
| { |
| syncExec(display, runnable); |
| } |
| } |
| |
| public static void syncExec(final Display display, final Runnable runnable) |
| { |
| try |
| { |
| if (display.isDisposed()) |
| { |
| return; |
| } |
| |
| display.syncExec(new Runnable() |
| { |
| public void run() |
| { |
| if (display.isDisposed()) |
| { |
| return; |
| } |
| |
| try |
| { |
| runnable.run(); |
| } |
| catch (SWTException ex) |
| { |
| if (ex.code != SWT.ERROR_WIDGET_DISPOSED) |
| { |
| throw ex; |
| } |
| |
| //$FALL-THROUGH$ |
| } |
| } |
| }); |
| } |
| catch (SWTException ex) |
| { |
| if (ex.code != SWT.ERROR_WIDGET_DISPOSED) |
| { |
| throw ex; |
| } |
| |
| //$FALL-THROUGH$ |
| } |
| } |
| |
| public static void timerExec(int milliseconds, final Runnable runnable) |
| { |
| final Display display = getDisplay(); |
| if (display != null) |
| { |
| timerExec(milliseconds, display, runnable); |
| } |
| } |
| |
| public static void timerExec(int milliseconds, final Display display, final Runnable runnable) |
| { |
| try |
| { |
| if (display.isDisposed()) |
| { |
| return; |
| } |
| |
| display.timerExec(milliseconds, new Runnable() |
| { |
| public void run() |
| { |
| if (display.isDisposed()) |
| { |
| return; |
| } |
| |
| try |
| { |
| runnable.run(); |
| } |
| catch (SWTException ex) |
| { |
| if (ex.code != SWT.ERROR_WIDGET_DISPOSED) |
| { |
| throw ex; |
| } |
| |
| //$FALL-THROUGH$ |
| } |
| } |
| }); |
| } |
| catch (SWTException ex) |
| { |
| if (ex.code != SWT.ERROR_WIDGET_DISPOSED) |
| { |
| throw ex; |
| } |
| |
| //$FALL-THROUGH$ |
| } |
| } |
| |
| public static IDialogSettings getOrCreateSection(IDialogSettings settings, String sectionName) |
| { |
| IDialogSettings section = settings.getSection(sectionName); |
| if (section == null) |
| { |
| section = settings.addNewSection(sectionName); |
| } |
| |
| return section; |
| } |
| |
| public static void dispose(Resource... resources) |
| { |
| for (int i = 0; i < resources.length; i++) |
| { |
| Resource resource = resources[i]; |
| if (resource != null && !resource.isDisposed()) |
| { |
| resource.dispose(); |
| } |
| } |
| } |
| |
| public static void simulateKey(char character) |
| { |
| Display display = getDisplay(); |
| |
| Event event = new Event(); |
| event.type = SWT.KeyDown; |
| event.character = character; |
| display.post(event); |
| |
| try |
| { |
| Thread.sleep(10); |
| } |
| catch (InterruptedException ex) |
| { |
| } |
| |
| event.type = SWT.KeyUp; |
| display.post(event); |
| |
| try |
| { |
| Thread.sleep(10); |
| } |
| catch (InterruptedException ex) |
| { |
| } |
| } |
| |
| public static String stripHTML(String html) |
| { |
| try |
| { |
| final StringBuilder builder = new StringBuilder(); |
| new ParserDelegator().parse(new StringReader(html), new HTMLEditorKit.ParserCallback() |
| { |
| @Override |
| public void handleText(char[] text, int pos) |
| { |
| builder.append(text); |
| } |
| }, Boolean.TRUE); |
| |
| return builder.toString(); |
| } |
| catch (IOException ex) |
| { |
| return html; |
| } |
| } |
| } |