blob: 23baf173908e4c943b92040177dcdf9961df376d [file] [log] [blame]
/*
* 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()));
}
}
}