/* * 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())); } } }