/******************************************************************************* * Copyright (c) 2004 - 2010 IBM Corporation 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: * IBM Corporation - initial API and implementation * Tom Schindl - modification to be os independent *******************************************************************************/ package org.eclipse.nebula.effects.stw; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; /** * Image Capture */ public class ImageCapture { public static void drawOnImage(Image myImage, Control control, int maxWidth, int maxHeight, boolean includeChildren) { // We need to be able to handle right-to-left coordinates too. In that case the bounds rectangle will be reversed from what we // think. We think the origin is upper-left, but the origin is really upper-right. To get out of this thinking we will // instead convert all bounds to display bounds so that they will all be left-to-right. if (myImage != null) { // Get the images of all of the children if (includeChildren && control instanceof Composite) { Display display = control.getDisplay(); Rectangle parentBounds = control.getParent() == null ? control.getBounds() : display.map(control.getParent(), null, control.getBounds()); // Need to clip the bounds to the size of the image so we get just what we need. Rectangle imgBounds = myImage.getBounds(); parentBounds.width = imgBounds.width; parentBounds.height = imgBounds.height; int parentRight = parentBounds.width+parentBounds.x; int parentBottom = parentBounds.height+parentBounds.y; Control[] children = ((Composite) control).getChildren(); GC myImageGC = new GC(myImage); try { int i = children.length; while (--i >= 0) { Control child = children[i]; // If the child is not visible then don't try and get its image // An example of where this would cause a problem is TabFolder where all the controls // for each page are children of the TabFolder, but only the visible one is being shown on the active page if (!child.isVisible()) continue; Rectangle childBounds = display.map(control, null, child.getBounds()); if (!parentBounds.intersects(childBounds)) continue; // Child is completely outside parent. Image childImage = getImage(child, parentRight - childBounds.x, parentBottom - childBounds.y, true); if (childImage != null) { try { // Paint the child image on top of our one // Since the child bounds and parent bounds are both in display coors, the difference between // the two is the offset of the child from the parent. myImageGC.drawImage(childImage, childBounds.x-parentBounds.x, childBounds.y-parentBounds.y); } finally { childImage.dispose(); } } } } finally { myImageGC.dispose(); } } } } public static Image getImage(Control control, int maxWidth, int maxHeight, boolean includeChildren) { Image myImage = getImage(control, maxWidth, maxHeight); drawOnImage(myImage, control, maxWidth, maxHeight, includeChildren); return myImage; } /** * Return the image of the argument. This includes the client and non-client area, but does not include any child controls. To get child control * use {@link ImageCapture#getImage(Control, int, int, boolean)}. * * @param aControl * @param maxWidth * @param maxHeight * @return image or <code>null</code> if not valid for some reason. (Like not yet sized). * * @since 1.1.0 */ public static Image getImage(Control aControl, int maxWidth, int maxHeight) { Rectangle rect = aControl.getBounds(); if (rect.width <= 0 || rect.height <= 0) return null; Image image = new Image(aControl.getDisplay(), Math.min(rect.width, maxWidth), Math.min(rect.height, maxHeight)); GC gc = new GC(image); // Need to handle cases where the GC font isn't automatically set by the control's image (e.g. CLabel) // see bug 98830 (https://bugs.eclipse.org/bugs/show_bug.cgi?id=98830) Font f = aControl.getFont(); if (f != null) gc.setFont(f); aControl.print(gc); gc.dispose(); return image; } }