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