• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.ide.eclipse.gltrace.widgets;
18 
19 import com.android.ide.eclipse.gltrace.GlTracePlugin;
20 
21 import org.eclipse.core.runtime.Status;
22 import org.eclipse.jface.dialogs.ErrorDialog;
23 import org.eclipse.swt.SWT;
24 import org.eclipse.swt.events.SelectionAdapter;
25 import org.eclipse.swt.events.SelectionEvent;
26 import org.eclipse.swt.events.SelectionListener;
27 import org.eclipse.swt.graphics.Color;
28 import org.eclipse.swt.graphics.GC;
29 import org.eclipse.swt.graphics.Image;
30 import org.eclipse.swt.graphics.ImageData;
31 import org.eclipse.swt.graphics.ImageLoader;
32 import org.eclipse.swt.graphics.Point;
33 import org.eclipse.swt.graphics.Rectangle;
34 import org.eclipse.swt.widgets.Canvas;
35 import org.eclipse.swt.widgets.Composite;
36 import org.eclipse.swt.widgets.Display;
37 import org.eclipse.swt.widgets.Event;
38 import org.eclipse.swt.widgets.Listener;
39 import org.eclipse.swt.widgets.ScrollBar;
40 
41 import java.io.File;
42 
43 public class ImageCanvas extends Canvas {
44     private static final int SCROLLBAR_INCREMENT = 20;
45 
46     private Point mOrigin;
47 
48     private ScrollBar mHorizontalScrollBar;
49     private ScrollBar mVerticalScrollBar;
50 
51     private Image mImage;
52     private boolean mFitToCanvas;
53 
ImageCanvas(Composite parent)54     public ImageCanvas(Composite parent) {
55         super(parent, SWT.NO_BACKGROUND | SWT.V_SCROLL | SWT.H_SCROLL);
56         mOrigin = new Point(0, 0);
57 
58         mHorizontalScrollBar = getHorizontalBar();
59         mVerticalScrollBar = getVerticalBar();
60 
61         mFitToCanvas = true;
62 
63         setScrollBarIncrements();
64         setScrollBarPageIncrements(getClientArea());
65 
66         updateScrollBars();
67 
68         SelectionListener scrollBarSelectionListener = new SelectionAdapter() {
69             @Override
70             public void widgetSelected(SelectionEvent e) {
71                 if (e.getSource() == mHorizontalScrollBar) {
72                     scrollHorizontally();
73                 } else {
74                     scrollVertically();
75                 }
76             }
77         };
78 
79         mHorizontalScrollBar.addSelectionListener(scrollBarSelectionListener);
80         mVerticalScrollBar.addSelectionListener(scrollBarSelectionListener);
81 
82         addListener(SWT.Resize,  new Listener() {
83             @Override
84             public void handleEvent(Event e) {
85                 setScrollBarPageIncrements(getClientArea());
86                 updateScrollBars();
87             }
88         });
89 
90         addListener(SWT.Paint, new Listener() {
91             @Override
92             public void handleEvent(Event e) {
93                 paintCanvas(e.gc);
94             }
95         });
96     }
97 
setFitToCanvas(boolean en)98     public void setFitToCanvas(boolean en) {
99         mFitToCanvas = en;
100         updateScrollBars();
101         redraw();
102     }
103 
setImage(Image image)104     public void setImage(Image image) {
105         if (mImage != null) {
106             mImage.dispose();
107         }
108 
109         mImage = image;
110         mOrigin = new Point(0, 0);
111         updateScrollBars();
112         redraw();
113     }
114 
updateScrollBars()115     private void updateScrollBars() {
116         Rectangle client = getClientArea();
117 
118         int imageWidth, imageHeight;
119         if (mImage != null & !mFitToCanvas) {
120             imageWidth = mImage.getBounds().width;
121             imageHeight = mImage.getBounds().height;
122         } else {
123             imageWidth = client.width;
124             imageHeight = client.height;
125         }
126 
127         mHorizontalScrollBar.setMaximum(imageWidth);
128         mVerticalScrollBar.setMaximum(imageHeight);
129         mHorizontalScrollBar.setThumb(Math.min(imageWidth, client.width));
130         mVerticalScrollBar.setThumb(Math.min(imageHeight, client.height));
131 
132         int hPage = imageWidth - client.width;
133         int vPage = imageHeight - client.height;
134         int hSelection = mHorizontalScrollBar.getSelection();
135         int vSelection = mVerticalScrollBar.getSelection();
136         if (hSelection >= hPage) {
137             if (hPage <= 0) {
138                 hSelection = 0;
139             }
140             mOrigin.x = -hSelection;
141         }
142 
143         if (vSelection >= vPage) {
144             if (vPage <= 0) {
145                 vSelection = 0;
146             }
147             mOrigin.y = -vSelection;
148         }
149 
150         redraw();
151     }
152 
setScrollBarPageIncrements(Rectangle clientArea)153     private void setScrollBarPageIncrements(Rectangle clientArea) {
154         mHorizontalScrollBar.setPageIncrement(clientArea.width);
155         mVerticalScrollBar.setPageIncrement(clientArea.height);
156     }
157 
setScrollBarIncrements()158     private void setScrollBarIncrements() {
159         // The default increment is 1 pixel. Assign a saner default.
160         mHorizontalScrollBar.setIncrement(SCROLLBAR_INCREMENT);
161         mVerticalScrollBar.setIncrement(SCROLLBAR_INCREMENT);
162     }
163 
scrollHorizontally()164     private void scrollHorizontally() {
165         if (mImage == null) {
166             return;
167         }
168 
169         int selection = mHorizontalScrollBar.getSelection();
170         int destX = -selection - mOrigin.x;
171         Rectangle imageBounds = mImage.getBounds();
172         scroll(destX, 0, 0, 0, imageBounds.width, imageBounds.height, false);
173         mOrigin.x = -selection;
174     }
175 
scrollVertically()176     private void scrollVertically() {
177         if (mImage == null) {
178             return;
179         }
180 
181         int selection = mVerticalScrollBar.getSelection();
182         int destY = -selection - mOrigin.y;
183         Rectangle imageBounds = mImage.getBounds();
184         scroll(0, destY, 0, 0, imageBounds.width, imageBounds.height, false);
185         mOrigin.y = -selection;
186     }
187 
paintCanvas(GC gc)188     private void paintCanvas(GC gc) {
189         gc.fillRectangle(getClientArea()); // clear entire client area
190         if (mImage == null) {
191             return;
192         }
193 
194         Rectangle rect = mImage.getBounds();
195         Rectangle client = getClientArea();
196 
197         if (mFitToCanvas && rect.width > 0 && rect.height > 0) {
198             double sx = (double) client.width / (double) rect.width;
199             double sy = (double) client.height / (double) rect.height;
200 
201             if (sx < sy) {
202                 // if we need to scale more horizontally, then reduce the client height
203                 // appropriately so that aspect ratios are maintained
204                 gc.drawImage(mImage,
205                         0, 0, rect.width, rect.height,
206                         0, 0, client.width, (int)(rect.height * sx));
207                 drawBorder(gc, 0, 0, client.width, (int)(rect.height * sx));
208             } else {
209                 // scale client width to maintain aspect ratio
210                 gc.drawImage(mImage,
211                         0, 0, rect.width, rect.height,
212                         0, 0, (int)(rect.width * sy), client.height);
213                 drawBorder(gc, 0, 0, (int)(rect.width * sy), client.height);
214             }
215         } else {
216             gc.drawImage(mImage, mOrigin.x, mOrigin.y);
217             drawBorder(gc, mOrigin.x, mOrigin.y, rect.width, rect.height);
218         }
219     }
220 
drawBorder(GC gc, int x, int y, int width, int height)221     private void drawBorder(GC gc, int x, int y, int width, int height) {
222         Color origFg = gc.getForeground();
223         gc.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
224         gc.drawRectangle(x, y, width, height);
225         gc.setForeground(origFg);
226     }
227 
228     @Override
dispose()229     public void dispose() {
230         if (mImage != null && !mImage.isDisposed()) {
231             mImage.dispose();
232         }
233     }
234 
exportImageTo(File file)235     public void exportImageTo(File file) {
236         if (mImage == null || file == null) {
237             return;
238         }
239 
240         ImageLoader imageLoader = new ImageLoader();
241         imageLoader.data = new ImageData[] { mImage.getImageData() };
242 
243         try {
244             imageLoader.save(file.getAbsolutePath(), SWT.IMAGE_PNG);
245         } catch (Exception e) {
246             ErrorDialog.openError(getShell(), "Save Image", "Error saving image",
247                     new Status(Status.ERROR, GlTracePlugin.PLUGIN_ID, e.toString()));
248         }
249     }
250 }
251