• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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 
18 package com.android.ide.eclipse.adt.internal.editors;
19 
20 import com.android.ide.eclipse.adt.AdtPlugin;
21 import com.android.sdklib.SdkConstants;
22 
23 import org.eclipse.jface.resource.ImageDescriptor;
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.graphics.Font;
26 import org.eclipse.swt.graphics.FontData;
27 import org.eclipse.swt.graphics.GC;
28 import org.eclipse.swt.graphics.Image;
29 import org.eclipse.swt.graphics.ImageData;
30 import org.eclipse.swt.graphics.Point;
31 import org.eclipse.swt.widgets.Display;
32 
33 import java.util.HashMap;
34 
35 /**
36  * Factory to generate icons for Android Editors.
37  * <p/>
38  * Icons are kept here and reused.
39  */
40 public class IconFactory {
41 
42     public static final int COLOR_RED     = SWT.COLOR_DARK_RED;
43     public static final int COLOR_GREEN   = SWT.COLOR_DARK_GREEN;
44     public static final int COLOR_BLUE    = SWT.COLOR_DARK_BLUE;
45     public static final int COLOR_DEFAULT = SWT.COLOR_BLACK;
46 
47     public static final int SHAPE_CIRCLE  = 'C';
48     public static final int SHAPE_RECT    = 'R';
49     public static final int SHAPE_DEFAULT = SHAPE_CIRCLE;
50 
51     private static IconFactory sInstance;
52 
53     private HashMap<String, Image> mIconMap = new HashMap<String, Image>();
54     private HashMap<String, ImageDescriptor> mImageDescMap = new HashMap<String, ImageDescriptor>();
55 
IconFactory()56     private IconFactory() {
57     }
58 
getInstance()59     public static synchronized IconFactory getInstance() {
60         if (sInstance == null) {
61             sInstance = new IconFactory();
62         }
63         return sInstance;
64     }
65 
Dispose()66     public void Dispose() {
67         // Dispose icons
68         for (Image icon : mIconMap.values()) {
69             // The map can contain null values
70             if (icon != null) {
71                 icon.dispose();
72             }
73         }
74         mIconMap.clear();
75     }
76 
77     /**
78      * Returns an Image for a given icon name.
79      * <p/>
80      * Callers should not dispose it.
81      *
82      * @param osName The leaf name, without the extension, of an existing icon in the
83      *        editor's "icons" directory. If it doesn't exists, a default icon will be
84      *        generated automatically based on the name.
85      */
getIcon(String osName)86     public Image getIcon(String osName) {
87         return getIcon(osName, COLOR_DEFAULT, SHAPE_DEFAULT);
88     }
89 
90     /**
91      * Returns an Image for a given icon name.
92      * <p/>
93      * Callers should not dispose it.
94      *
95      * @param osName The leaf name, without the extension, of an existing icon in the
96      *        editor's "icons" directory. If it doesn't exists, a default icon will be
97      *        generated automatically based on the name.
98      * @param color The color of the text in the automatically generated icons,
99      *        one of COLOR_DEFAULT, COLOR_RED, COLOR_BLUE or COLOR_RED.
100      * @param shape The shape of the icon in the automatically generated icons,
101      *        one of SHAPE_DEFAULT, SHAPE_CIRCLE or SHAPE_RECT.
102      */
getIcon(String osName, int color, int shape)103     public Image getIcon(String osName, int color, int shape) {
104         String key = Character.toString((char) shape) + Integer.toString(color) + osName;
105         Image icon = mIconMap.get(key);
106         if (icon == null && !mIconMap.containsKey(key)) {
107             ImageDescriptor id = getImageDescriptor(osName, color, shape);
108             if (id != null) {
109                 icon = id.createImage();
110             }
111             // Note that we store null references in the icon map, to avoid looking them
112             // up every time. If it didn't exist once, it will not exist later.
113             mIconMap.put(key, icon);
114         }
115         return icon;
116     }
117 
118     /**
119      * Returns an ImageDescriptor for a given icon name.
120      * <p/>
121      * Callers should not dispose it.
122      *
123      * @param osName The leaf name, without the extension, of an existing icon in the
124      *        editor's "icons" directory. If it doesn't exists, a default icon will be
125      *        generated automatically based on the name.
126      */
getImageDescriptor(String osName)127     public ImageDescriptor getImageDescriptor(String osName) {
128         return getImageDescriptor(osName, COLOR_DEFAULT, SHAPE_DEFAULT);
129     }
130 
131     /**
132      * Returns an ImageDescriptor for a given icon name.
133      * <p/>
134      * Callers should not dispose it.
135      *
136      * @param osName The leaf name, without the extension, of an existing icon in the
137      *        editor's "icons" directory. If it doesn't exists, a default icon will be
138      *        generated automatically based on the name.
139      * @param color The color of the text in the automatically generated icons.
140      *        one of COLOR_DEFAULT, COLOR_RED, COLOR_BLUE or COLOR_RED.
141      * @param shape The shape of the icon in the automatically generated icons,
142      *        one of SHAPE_DEFAULT, SHAPE_CIRCLE or SHAPE_RECT.
143      */
getImageDescriptor(String osName, int color, int shape)144     public ImageDescriptor getImageDescriptor(String osName, int color, int shape) {
145         String key = Character.toString((char) shape) + Integer.toString(color) + osName;
146         ImageDescriptor id = mImageDescMap.get(key);
147         if (id == null && !mImageDescMap.containsKey(key)) {
148             id = AdtPlugin.imageDescriptorFromPlugin(
149                     AdtPlugin.PLUGIN_ID,
150                     String.format("/icons/%1$s.png", osName)); //$NON-NLS-1$
151 
152             if (id == null) {
153                 id = new LetterImageDescriptor(osName.charAt(0), color, shape);
154             }
155 
156             // Note that we store null references in the icon map, to avoid looking them
157             // up every time. If it didn't exist once, it will not exist later.
158             mImageDescMap.put(key, id);
159         }
160         return id;
161     }
162 
163     /**
164      * A simple image description that generates a 16x16 image which consists
165      * of a colored letter inside a black & white circle.
166      */
167     private static class LetterImageDescriptor extends ImageDescriptor {
168 
169         private final char mLetter;
170         private final int mColor;
171         private final int mShape;
172 
LetterImageDescriptor(char letter, int color, int shape)173         public LetterImageDescriptor(char letter, int color, int shape) {
174             mLetter = letter;
175             mColor = color;
176             mShape = shape;
177         }
178 
179         @Override
getImageData()180         public ImageData getImageData() {
181 
182             final int SX = 15;
183             final int SY = 15;
184             final int RX = 4;
185             final int RY = 4;
186 
187             Display display = Display.getCurrent();
188             if (display == null) {
189                 return null;
190             }
191 
192             Image image = new Image(display, SX, SY);
193 
194             image.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
195 
196             GC gc = new GC(image);
197             gc.setAdvanced(true);
198             gc.setAntialias(SWT.ON);
199             gc.setTextAntialias(SWT.ON);
200 
201             gc.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
202             if (mShape == SHAPE_CIRCLE) {
203                 gc.fillOval(0, 0, SX - 1, SY - 1);
204             } else if (mShape == SHAPE_RECT) {
205                 gc.fillRoundRectangle(0, 0, SX - 1, SY - 1, RX, RY);
206             }
207 
208             gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
209             gc.setLineWidth(1);
210             if (mShape == SHAPE_CIRCLE) {
211                 gc.drawOval(0, 0, SX - 1, SY - 1);
212             } else if (mShape == SHAPE_RECT) {
213                 gc.drawRoundRectangle(0, 0, SX - 1, SY - 1, RX, RY);
214             }
215 
216             // Get a bold version of the default system font, if possible.
217             Font font = display.getSystemFont();
218             FontData[] fds = font.getFontData();
219             fds[0].setStyle(SWT.BOLD);
220             // use 3/4th of the circle diameter for the font size (in pixels)
221             // and convert it to "font points" (font points in SWT are hardcoded in an
222             // arbitrary 72 dpi and then converted in real pixels using whatever is
223             // indicated by getDPI -- at least that's how it works under Win32).
224             fds[0].setHeight((int) ((SY + 1) * 3./4. * 72./display.getDPI().y));
225             // Note: win32 implementation always uses fds[0] so we change just that one.
226             // getFontData indicates that the array of fd is really an unusual thing for X11.
227             font = new Font(display, fds);
228             gc.setFont(font);
229             gc.setForeground(display.getSystemColor(mColor));
230 
231             // Text measurement varies so slightly depending on the platform
232             int ofx = 0;
233             int ofy = 0;
234             if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS) {
235                 ofx = +1;
236                 ofy = -1;
237             }
238 
239             String s = Character.toString(mLetter).toUpperCase();
240             Point p = gc.textExtent(s);
241             int tx = (SX + ofx - p.x) / 2;
242             int ty = (SY + ofy - p.y) / 2;
243             gc.drawText(s, tx, ty, true /* isTransparent */);
244 
245             font.dispose();
246             gc.dispose();
247 
248             ImageData data = image.getImageData();
249             image.dispose();
250             return data;
251         }
252 
253     }
254 
255 }
256