Java tutorial
/* * Copyright (c) 2014 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.ReflectUtil; import org.eclipse.jface.dialogs.IDialogPage; import org.eclipse.jface.wizard.ProgressMonitorPart; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; 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.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Scrollable; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.Widget; import org.eclipse.ui.PlatformUI; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicReference; /** * @author Ed Merks */ public abstract class Capture<T> { protected abstract T create(Shell shell); protected abstract Shell getShell(T element); protected abstract void open(T element); public Image capture() { final AtomicReference<Image> image = new AtomicReference<Image>(); final Display display = PlatformUI.getWorkbench().getDisplay(); final org.eclipse.jface.dialogs.Dialog backgroundDialog = new org.eclipse.jface.dialogs.Dialog( (Shell) null) { { setShellStyle(SWT.MAX); } @Override protected Control createDialogArea(Composite parent) { Control control = super.createDialogArea(parent); control.setBackground(display.getSystemColor(SWT.COLOR_WHITE)); return control; } }; UIUtil.asyncExec(new Runnable() { public void run() { backgroundDialog.open(); } }); while (backgroundDialog.getShell() == null) { try { Thread.sleep(100); } catch (InterruptedException ex) { // Ignore. } } final Shell backgroundShell = backgroundDialog.getShell(); final T element = new WorkUnit<T, RuntimeException>() { @Override protected T doExecute() { backgroundShell.setMaximized(true); return create(backgroundShell); } }.execute(); UIUtil.asyncExec(new Runnable() { public void run() { open(element); } }); UIUtil.asyncExec(new Runnable() { public void run() { Shell shell = getShell(element); Rectangle bounds = shell.getBounds(); bounds.x = 30; bounds.y = 50; shell.setBounds(bounds); } }); while (!new WorkUnit<Boolean, RuntimeException>() { @Override protected Boolean doExecute() { return isReady(element); } }.execute()) { try { Thread.sleep(100); } catch (InterruptedException ex) { // Ignore. } } try { Thread.sleep(1000); } catch (InterruptedException ex) { // Ignore. } new WorkUnit.Void<RuntimeException>() { @Override protected void doProcess() { preprocess(element); } }.execute(); new WorkUnit.Void<RuntimeException>() { @Override protected void doProcess() { postProcess(element); } }.execute(); new WorkUnit.Void<RuntimeException>() { @Override protected void doProcess() { image.set(capture(element)); } }.execute(); new WorkUnit.Void<RuntimeException>() { @Override protected void doProcess() { close(element); backgroundShell.close(); } }.execute(); return image.get(); } protected Control getControl(T element) { return getShell(element); } protected boolean isReady(T element) { Shell shell = getShell(element); if (shell == null) { return false; } if (shell.getShells().length > 1) { return false; } return true; } protected void preprocess(T element) { } protected void postProcess(T element) { Button defaultButton = getShell(element).getDefaultButton(); if (defaultButton != null) { ReflectUtil.invokeMethod(ReflectUtil.getMethod(Button.class, "setDefault", boolean.class), defaultButton, false); } } protected Image capture(T element) { return AccessUtil.capture(getControl(element)); } protected Image capture(IDialogPage page, Map<Control, Image> decorations) { Control control = page.getControl(); // Get the control of the overall page. Composite pageControl = control.getParent().getParent().getParent(); Control[] children = pageControl.getChildren(); // Get the overall wizard control. Composite wizardControl = pageControl.getParent(); // Compute the bounds to capture by extending the bounds of the page control to include the title area but to exclude the bottom button area. Rectangle bounds = pageControl.getBounds(); Point size = children[1].getSize(); bounds.height += bounds.y - 2; bounds.y = 0; bounds.height -= size.y; Point displayOffset = wizardControl.toDisplay(bounds.x, bounds.y); Image result = AccessUtil.capture(control.getDisplay(), new Rectangle(displayOffset.x, displayOffset.y, bounds.width, bounds.height)); if (decorations != null && !decorations.isEmpty()) { decorate(result, wizardControl, bounds, decorations); } return result; } protected void decorate(Image image, Control parent, Rectangle bounds, Map<Control, Image> decorations) { GC gc = new GC(image); for (Entry<Control, Image> entry : decorations.entrySet()) { Control control = entry.getKey(); Image decoration = entry.getValue(); if (decoration != null) { Rectangle controlBounds = control.getBounds(); int border = control.getBorderWidth(); Point controlLocation = control.getParent() .toDisplay(controlBounds.x + controlBounds.width - 1 - border, controlBounds.y - border); Point relativeControlLocation = parent.toControl(controlLocation); Rectangle imageBounds = decoration.getBounds(); imageBounds.x = bounds.x + relativeControlLocation.x - (imageBounds.width - 1) - 11; imageBounds.y = bounds.y + relativeControlLocation.y + 11; if (control instanceof Scrollable) { Scrollable scrollable = (Scrollable) control; Rectangle clientArea = scrollable.getClientArea(); imageBounds.x -= controlBounds.width - clientArea.width - 2 * border; if (control instanceof Tree) { imageBounds.y += ((Tree) control).getHeaderHeight(); } if (control instanceof Table) { imageBounds.y += ((Table) control).getHeaderHeight(); } } gc.drawImage(decoration, imageBounds.x, imageBounds.y); } } gc.dispose(); } protected Image getImage(final Control control) { Point size = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); if (control instanceof Combo) { Combo combo = (Combo) control; GC gc = new GC(control); Point textExtent = gc.textExtent(combo.getText()); size.x = textExtent.x + 30; gc.dispose(); } control.setSize(size); AccessUtil.busyWait(10); Image result = AccessUtil.capture(control); return result; } protected <W extends Widget> W getWidget(T element, String key) { return AccessUtil.getWidget(getShell(element), key); } protected Image getImage(T element, String key) { Widget widget = AccessUtil.getWidget(getShell(element), key); if (widget instanceof ToolItem) { ToolItem toolItem = (ToolItem) widget; Image image = toolItem.getImage(); return new Image(image.getDevice(), image.getImageData()); } if (widget instanceof Button) { Button button = (Button) widget; Shell shell = button.getShell(); Color background = button.getBackground(); boolean isEnabled = button.isEnabled(); try { int style = button.getStyle(); if ((style & SWT.PUSH) != 0) { button.setBackground(shell.getDisplay().getSystemColor(SWT.COLOR_WHITE)); } button.setEnabled(true); AccessUtil.busyWait(1000); return AccessUtil.capture(button); } finally { button.setBackground(background); button.setEnabled(isEnabled); } } if (widget instanceof ProgressMonitorPart) { ProgressMonitorPart progressMonitorPart = (ProgressMonitorPart) widget; progressMonitorPart.setSize(170, progressMonitorPart.getSize().y); AccessUtil.busyWait(10); return AccessUtil.capture(progressMonitorPart); } if (widget instanceof Text) { Text text = (Text) widget; return getImage(text); } if (widget instanceof Combo) { Combo combo = (Combo) widget; return getImage(combo); } if (widget instanceof Control) { Control control = (Control) widget; return AccessUtil.capture(control); } throw new UnsupportedOperationException("Unexpected widget " + widget); } protected void close(T element) { Shell shell = getShell(element); shell.close(); } /** * @author Ed Merks */ public static abstract class Window<W extends org.eclipse.jface.window.Window> extends Capture<W> { @Override protected Shell getShell(W window) { return window.getShell(); } @Override protected void open(W window) { window.open(); } } /** * @author Ed Merks */ public static abstract class Dialog<D extends org.eclipse.swt.widgets.Dialog> extends Capture<D> { @Override protected Shell getShell(D dialog) { return dialog.getParent(); } @Override protected void open(D dialog) { ReflectUtil.invokeMethod(ReflectUtil.getMethod(dialog.getClass(), "open"), dialog); } } }