1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
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.adt.internal.editors.layout.gle2;
18 
19 import com.android.annotations.NonNull;
20 import com.android.annotations.Nullable;
21 
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.custom.CLabel;
24 import org.eclipse.swt.events.MouseEvent;
25 import org.eclipse.swt.events.MouseTrackListener;
26 import org.eclipse.swt.events.PaintEvent;
27 import org.eclipse.swt.events.PaintListener;
28 import org.eclipse.swt.graphics.Color;
29 import org.eclipse.swt.graphics.GC;
30 import org.eclipse.swt.graphics.Image;
31 import org.eclipse.swt.graphics.Point;
32 import org.eclipse.swt.graphics.Rectangle;
33 import org.eclipse.swt.widgets.Canvas;
34 import org.eclipse.swt.widgets.Composite;
35 
36 /**
37  * An ImageControl which simply renders an image, with optional margins and tooltips. This
38  * is useful since a {@link CLabel}, even without text, will hide the image when there is
39  * not enough room to fully fit it.
40  * <p>
41  * The image is always rendered left and top aligned.
42  */
43 public class ImageControl extends Canvas implements MouseTrackListener {
44     private Image mImage;
45     private int mLeftMargin;
46     private int mTopMargin;
47     private int mRightMargin;
48     private int mBottomMargin;
49     private boolean mDisposeImage = true;
50     private boolean mMouseIn;
51     private Color mHoverColor;
52     private float mScale = 1.0f;
53 
54     /**
55      * Creates an ImageControl rendering the given image, which will be disposed when this
56      * control is disposed (unless the {@link #setDisposeImage} method is called to turn
57      * off auto dispose).
58      *
59      * @param parent the parent to add the image control to
60      * @param style the SWT style to use
61      * @param image the image to be rendered, which must not be null and should be unique
62      *            for this image control since it will be disposed by this control when
63      *            the control is disposed (unless the {@link #setDisposeImage} method is
64      *            called to turn off auto dispose)
65      */
ImageControl(@onNull Composite parent, int style, @Nullable Image image)66     public ImageControl(@NonNull Composite parent, int style, @Nullable Image image) {
67         super(parent, style | SWT.NO_FOCUS | SWT.DOUBLE_BUFFERED);
68         mImage = image;
69 
70         addPaintListener(new PaintListener() {
71             @Override
72             public void paintControl(PaintEvent event) {
73                 onPaint(event);
74             }
75         });
76     }
77 
78     @Nullable
getImage()79     public Image getImage() {
80         return mImage;
81     }
82 
setImage(@ullable Image image)83     public void setImage(@Nullable Image image) {
84         if (mDisposeImage && mImage != null) {
85             mImage.dispose();
86         }
87         mImage = image;
88         redraw();
89     }
90 
fitToWidth(int width)91     public void fitToWidth(int width) {
92         if (mImage == null) {
93             return;
94         }
95         Rectangle imageRect = mImage.getBounds();
96         int imageWidth = imageRect.width;
97         if (imageWidth <= width) {
98             mScale = 1.0f;
99             return;
100         }
101 
102         mScale = width / (float) imageWidth;
103         redraw();
104     }
105 
setScale(float scale)106     public void setScale(float scale) {
107         mScale = scale;
108     }
109 
getScale()110     public float getScale() {
111         return mScale;
112     }
113 
setHoverColor(@ullable Color hoverColor)114     public void setHoverColor(@Nullable Color hoverColor) {
115         if (mHoverColor != null) {
116             removeMouseTrackListener(this);
117         }
118         mHoverColor = hoverColor;
119         if (hoverColor != null) {
120             addMouseTrackListener(this);
121         }
122     }
123 
124     @Nullable
getHoverColor()125     public Color getHoverColor() {
126         return mHoverColor;
127     }
128 
129     @Override
dispose()130     public void dispose() {
131         super.dispose();
132 
133         if (mDisposeImage && mImage != null && !mImage.isDisposed()) {
134             mImage.dispose();
135         }
136         mImage = null;
137     }
138 
setDisposeImage(boolean disposeImage)139     public void setDisposeImage(boolean disposeImage) {
140         mDisposeImage = disposeImage;
141     }
142 
getDisposeImage()143     public boolean getDisposeImage() {
144         return mDisposeImage;
145     }
146 
147     @Override
computeSize(int wHint, int hHint, boolean changed)148     public Point computeSize(int wHint, int hHint, boolean changed) {
149         checkWidget();
150         Point e = new Point(0, 0);
151         if (mImage != null) {
152             Rectangle r = mImage.getBounds();
153             if (mScale != 1.0f) {
154                 e.x += mScale * r.width;
155                 e.y += mScale * r.height;
156             } else {
157                 e.x += r.width;
158                 e.y += r.height;
159             }
160         }
161         if (wHint == SWT.DEFAULT) {
162             e.x += mLeftMargin + mRightMargin;
163         } else {
164             e.x = wHint;
165         }
166         if (hHint == SWT.DEFAULT) {
167             e.y += mTopMargin + mBottomMargin;
168         } else {
169             e.y = hHint;
170         }
171 
172         return e;
173     }
174 
onPaint(PaintEvent event)175     private void onPaint(PaintEvent event) {
176         Rectangle rect = getClientArea();
177         if (mImage == null || rect.width == 0 || rect.height == 0) {
178             return;
179         }
180 
181         GC gc = event.gc;
182         Rectangle imageRect = mImage.getBounds();
183         int imageHeight = imageRect.height;
184         int imageWidth = imageRect.width;
185         int destWidth = imageWidth;
186         int destHeight = imageHeight;
187 
188         int oldGcAlias = gc.getAntialias();
189         int oldGcInterpolation = gc.getInterpolation();
190         if (mScale != 1.0f) {
191             destWidth = (int) (mScale * destWidth);
192             destHeight = (int) (mScale * destHeight);
193             gc.setAntialias(SWT.ON);
194             gc.setInterpolation(SWT.HIGH);
195         }
196 
197         gc.drawImage(mImage, 0, 0, imageWidth, imageHeight, rect.x + mLeftMargin, rect.y
198                 + mTopMargin, destWidth, destHeight);
199 
200         gc.setAntialias(oldGcAlias);
201         gc.setInterpolation(oldGcInterpolation);
202 
203         if (mHoverColor != null && mMouseIn) {
204             gc.setAlpha(60);
205             gc.setBackground(mHoverColor);
206             gc.setLineWidth(1);
207             gc.fillRectangle(0, 0, destWidth, destHeight);
208         }
209     }
210 
setMargins(int leftMargin, int topMargin, int rightMargin, int bottomMargin)211     public void setMargins(int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
212         checkWidget();
213         mLeftMargin = Math.max(0, leftMargin);
214         mTopMargin = Math.max(0, topMargin);
215         mRightMargin = Math.max(0, rightMargin);
216         mBottomMargin = Math.max(0, bottomMargin);
217         redraw();
218     }
219 
220     // ---- Implements MouseTrackListener ----
221 
222     @Override
mouseEnter(MouseEvent e)223     public void mouseEnter(MouseEvent e) {
224         mMouseIn = true;
225         if (mHoverColor != null) {
226             redraw();
227         }
228     }
229 
230     @Override
mouseExit(MouseEvent e)231     public void mouseExit(MouseEvent e) {
232         mMouseIn = false;
233         if (mHoverColor != null) {
234             redraw();
235         }
236     }
237 
238     @Override
mouseHover(MouseEvent e)239     public void mouseHover(MouseEvent e) {
240     }
241 }
242