diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/widgets/ImageCanvas.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/widgets/ImageCanvas.java | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/widgets/ImageCanvas.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/widgets/ImageCanvas.java new file mode 100644 index 000000000..23baf1739 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/widgets/ImageCanvas.java @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2012 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.ide.eclipse.gltrace.widgets; + +import com.android.ide.eclipse.gltrace.GlTracePlugin; + +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +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.Canvas; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.ScrollBar; + +import java.io.File; + +public class ImageCanvas extends Canvas { + private static final int SCROLLBAR_INCREMENT = 20; + + private Point mOrigin; + + private ScrollBar mHorizontalScrollBar; + private ScrollBar mVerticalScrollBar; + + private Image mImage; + private boolean mFitToCanvas; + + public ImageCanvas(Composite parent) { + super(parent, SWT.NO_BACKGROUND | SWT.V_SCROLL | SWT.H_SCROLL); + mOrigin = new Point(0, 0); + + mHorizontalScrollBar = getHorizontalBar(); + mVerticalScrollBar = getVerticalBar(); + + mFitToCanvas = true; + + setScrollBarIncrements(); + setScrollBarPageIncrements(getClientArea()); + + updateScrollBars(); + + SelectionListener scrollBarSelectionListener = new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + if (e.getSource() == mHorizontalScrollBar) { + scrollHorizontally(); + } else { + scrollVertically(); + } + } + }; + + mHorizontalScrollBar.addSelectionListener(scrollBarSelectionListener); + mVerticalScrollBar.addSelectionListener(scrollBarSelectionListener); + + addListener(SWT.Resize, new Listener() { + @Override + public void handleEvent(Event e) { + setScrollBarPageIncrements(getClientArea()); + updateScrollBars(); + } + }); + + addListener(SWT.Paint, new Listener() { + @Override + public void handleEvent(Event e) { + paintCanvas(e.gc); + } + }); + } + + public void setFitToCanvas(boolean en) { + mFitToCanvas = en; + updateScrollBars(); + redraw(); + } + + public void setImage(Image image) { + if (mImage != null) { + mImage.dispose(); + } + + mImage = image; + mOrigin = new Point(0, 0); + updateScrollBars(); + redraw(); + } + + private void updateScrollBars() { + Rectangle client = getClientArea(); + + int imageWidth, imageHeight; + if (mImage != null & !mFitToCanvas) { + imageWidth = mImage.getBounds().width; + imageHeight = mImage.getBounds().height; + } else { + imageWidth = client.width; + imageHeight = client.height; + } + + mHorizontalScrollBar.setMaximum(imageWidth); + mVerticalScrollBar.setMaximum(imageHeight); + mHorizontalScrollBar.setThumb(Math.min(imageWidth, client.width)); + mVerticalScrollBar.setThumb(Math.min(imageHeight, client.height)); + + int hPage = imageWidth - client.width; + int vPage = imageHeight - client.height; + int hSelection = mHorizontalScrollBar.getSelection(); + int vSelection = mVerticalScrollBar.getSelection(); + if (hSelection >= hPage) { + if (hPage <= 0) { + hSelection = 0; + } + mOrigin.x = -hSelection; + } + + if (vSelection >= vPage) { + if (vPage <= 0) { + vSelection = 0; + } + mOrigin.y = -vSelection; + } + + redraw(); + } + + private void setScrollBarPageIncrements(Rectangle clientArea) { + mHorizontalScrollBar.setPageIncrement(clientArea.width); + mVerticalScrollBar.setPageIncrement(clientArea.height); + } + + private void setScrollBarIncrements() { + // The default increment is 1 pixel. Assign a saner default. + mHorizontalScrollBar.setIncrement(SCROLLBAR_INCREMENT); + mVerticalScrollBar.setIncrement(SCROLLBAR_INCREMENT); + } + + private void scrollHorizontally() { + if (mImage == null) { + return; + } + + int selection = mHorizontalScrollBar.getSelection(); + int destX = -selection - mOrigin.x; + Rectangle imageBounds = mImage.getBounds(); + scroll(destX, 0, 0, 0, imageBounds.width, imageBounds.height, false); + mOrigin.x = -selection; + } + + private void scrollVertically() { + if (mImage == null) { + return; + } + + int selection = mVerticalScrollBar.getSelection(); + int destY = -selection - mOrigin.y; + Rectangle imageBounds = mImage.getBounds(); + scroll(0, destY, 0, 0, imageBounds.width, imageBounds.height, false); + mOrigin.y = -selection; + } + + private void paintCanvas(GC gc) { + gc.fillRectangle(getClientArea()); // clear entire client area + if (mImage == null) { + return; + } + + Rectangle rect = mImage.getBounds(); + Rectangle client = getClientArea(); + + if (mFitToCanvas && rect.width > 0 && rect.height > 0) { + double sx = (double) client.width / (double) rect.width; + double sy = (double) client.height / (double) rect.height; + + if (sx < sy) { + // if we need to scale more horizontally, then reduce the client height + // appropriately so that aspect ratios are maintained + gc.drawImage(mImage, + 0, 0, rect.width, rect.height, + 0, 0, client.width, (int)(rect.height * sx)); + drawBorder(gc, 0, 0, client.width, (int)(rect.height * sx)); + } else { + // scale client width to maintain aspect ratio + gc.drawImage(mImage, + 0, 0, rect.width, rect.height, + 0, 0, (int)(rect.width * sy), client.height); + drawBorder(gc, 0, 0, (int)(rect.width * sy), client.height); + } + } else { + gc.drawImage(mImage, mOrigin.x, mOrigin.y); + drawBorder(gc, mOrigin.x, mOrigin.y, rect.width, rect.height); + } + } + + private void drawBorder(GC gc, int x, int y, int width, int height) { + Color origFg = gc.getForeground(); + gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); + gc.drawRectangle(x, y, width, height); + gc.setForeground(origFg); + } + + @Override + public void dispose() { + if (mImage != null && !mImage.isDisposed()) { + mImage.dispose(); + } + } + + public void exportImageTo(File file) { + if (mImage == null || file == null) { + return; + } + + ImageLoader imageLoader = new ImageLoader(); + imageLoader.data = new ImageData[] { mImage.getImageData() }; + + try { + imageLoader.save(file.getAbsolutePath(), SWT.IMAGE_PNG); + } catch (Exception e) { + ErrorDialog.openError(getShell(), "Save Image", "Error saving image", + new Status(Status.ERROR, GlTracePlugin.PLUGIN_ID, e.toString())); + } + } +} |