/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.ddmuilib; import com.android.ddmlib.Device; import com.android.ddmlib.Log; import com.android.ddmlib.RawImage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.ImageLoader; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Dialog; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import java.io.IOException; /** * Gather a screen shot from the device and save it to a file. */ public class ScreenShotDialog extends Dialog { private Label mBusyLabel; private Label mImageLabel; private Button mSave; private Device mDevice; /** * Create with default style. */ public ScreenShotDialog(Shell parent) { this(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); } /** * Create with app-defined style. */ public ScreenShotDialog(Shell parent, int style) { super(parent, style); } /** * Prepare and display the dialog. * @param device The {@link Device} from which to get the screenshot. */ public void open(Device device) { mDevice = device; Shell parent = getParent(); Shell shell = new Shell(parent, getStyle()); shell.setText("Device Screen Capture"); createContents(shell); shell.pack(); shell.open(); updateDeviceImage(shell); Display display = parent.getDisplay(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } } /* * Create the screen capture dialog contents. */ private void createContents(final Shell shell) { GridData data; shell.setLayout(new GridLayout(3, true)); // title/"capturing" label mBusyLabel = new Label(shell, SWT.NONE); mBusyLabel.setText("Preparing..."); data = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); data.horizontalSpan = 3; mBusyLabel.setLayoutData(data); // space for the image mImageLabel = new Label(shell, SWT.BORDER); data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); data.horizontalSpan = 3; mImageLabel.setLayoutData(data); Display display = shell.getDisplay(); mImageLabel.setImage(ImageHelper.createPlaceHolderArt(display, 50, 50, display.getSystemColor(SWT.COLOR_BLUE))); // "refresh" button Button refresh = new Button(shell, SWT.PUSH); refresh.setText("Refresh"); data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); data.widthHint = 80; refresh.setLayoutData(data); refresh.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updateDeviceImage(shell); } }); // "save" button mSave = new Button(shell, SWT.PUSH); mSave.setText("Save"); data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); data.widthHint = 80; mSave.setLayoutData(data); mSave.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { saveImage(shell); } }); // "done" button Button done = new Button(shell, SWT.PUSH); done.setText("Done"); data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER); data.widthHint = 80; done.setLayoutData(data); done.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { shell.close(); } }); shell.setDefaultButton(done); } /* * Capture a new image from the device. */ private void updateDeviceImage(Shell shell) { mBusyLabel.setText("Capturing..."); // no effect shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT)); Image image = getDeviceImage(); if (image == null) { Display display = shell.getDisplay(); image = ImageHelper.createPlaceHolderArt(display, 320, 240, display.getSystemColor(SWT.COLOR_BLUE)); mSave.setEnabled(false); mBusyLabel.setText("Screen not available"); } else { mSave.setEnabled(true); mBusyLabel.setText("Captured image:"); } mImageLabel.setImage(image); mImageLabel.pack(); shell.pack(); // there's no way to restore old cursor; assume it's ARROW shell.setCursor(shell.getDisplay().getSystemCursor(SWT.CURSOR_ARROW)); } /* * Grab an image from an ADB-connected device. */ private Image getDeviceImage() { RawImage rawImage; try { rawImage = mDevice.getScreenshot(); } catch (IOException ioe) { Log.w("ddms", "Unable to get frame buffer: " + ioe.getMessage()); return null; } // device/adb not available? if (rawImage == null) return null; // convert raw data to an Image assert rawImage.bpp == 16; PaletteData palette = new PaletteData(0xf800, 0x07e0, 0x001f); ImageData imageData = new ImageData(rawImage.width, rawImage.height, rawImage.bpp, palette, 1, rawImage.data); return new Image(getParent().getDisplay(), imageData); } /* * Prompt the user to save the image to disk. */ private void saveImage(Shell shell) { FileDialog dlg = new FileDialog(shell, SWT.SAVE); String fileName; dlg.setText("Save image..."); dlg.setFileName("device.png"); dlg.setFilterPath(DdmUiPreferences.getStore().getString("lastImageSaveDir")); dlg.setFilterNames(new String[] { "PNG Files (*.png)" }); dlg.setFilterExtensions(new String[] { "*.png" //$NON-NLS-1$ }); fileName = dlg.open(); if (fileName != null) { DdmUiPreferences.getStore().setValue("lastImageSaveDir", dlg.getFilterPath()); Log.i("ddms", "Saving image to " + fileName); ImageData imageData = mImageLabel.getImage().getImageData(); try { WritePng.savePng(fileName, imageData); } catch (IOException ioe) { Log.w("ddms", "Unable to save " + fileName + ": " + ioe); } if (false) { ImageLoader loader = new ImageLoader(); loader.data = new ImageData[] { imageData }; // PNG writing not available until 3.3? See bug at: // https://bugs.eclipse.org/bugs/show_bug.cgi?id=24697 // GIF writing only works for 8 bits // JPEG uses lossy compression // BMP has screwed-up colors loader.save(fileName, SWT.IMAGE_JPEG); } } } }