Skip to content

Package: NativeWidgetHelper$ImageRegistryServiceCustomizer

NativeWidgetHelper$ImageRegistryServiceCustomizer

nameinstructionbranchcomplexitylinemethod
addingService(ServiceReference)
M: 0 C: 13
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
lambda$0(ImageRegistryService)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$1(ImageRegistryService)
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
lambda$2()
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
modifiedService(ServiceReference, ImageRegistryService)
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
onUI(Runnable)
M: 3 C: 8
73%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 5
83%
M: 0 C: 1
100%
removedService(ServiceReference, ImageRegistryService)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
updateImages(ImageRegistryService)
M: 5 C: 18
78%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 3 C: 7
70%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2019 EclipseSource Muenchen GmbH and others.
3: *
4: * All rights reserved. This program and the accompanying materials
5: * are made available under the terms of the Eclipse Public License 2.0
6: * which accompanies this distribution, and is available at
7: * https://www.eclipse.org/legal/epl-2.0/
8: *
9: * SPDX-License-Identifier: EPL-2.0
10: *
11: * Contributors:
12: * jfaltermeier - initial API and implementation
13: * Christian W. Damus - bug 545686
14: ******************************************************************************/
15: /*******************************************************************************
16: * Copyright (c) 2006, 2014 Tom Schindl and others.
17: * All rights reserved. This program and the accompanying materials
18: * are made available under the terms of the Eclipse Public License 2.0
19: * which accompanies this distribution, and is available at
20: * https://www.eclipse.org/legal/epl-2.0/
21: *
22: * SPDX-License-Identifier: EPL-2.0
23: *
24: * Contributors:
25: * Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
26: * Florian Potschka <signalrauschen@gmail.com> - Bug 260061
27: * Alexander Ljungberg <siker@norwinter.com> - Bug 260061
28: * Jeanderson Candido <http://jeandersonbc.github.io> - Bug 414565
29: *******************************************************************************/
30: package org.eclipse.emf.ecp.view.spi.table.celleditor.rcp;
31:
32: import java.util.concurrent.locks.Lock;
33: import java.util.concurrent.locks.ReentrantLock;
34:
35: import org.eclipse.emf.ecp.view.spi.util.swt.ImageRegistryService;
36: import org.eclipse.swt.SWT;
37: import org.eclipse.swt.graphics.Color;
38: import org.eclipse.swt.graphics.GC;
39: import org.eclipse.swt.graphics.Image;
40: import org.eclipse.swt.graphics.ImageData;
41: import org.eclipse.swt.graphics.Point;
42: import org.eclipse.swt.widgets.Button;
43: import org.eclipse.swt.widgets.Control;
44: import org.eclipse.swt.widgets.Display;
45: import org.eclipse.swt.widgets.Shell;
46: import org.osgi.framework.Bundle;
47: import org.osgi.framework.FrameworkUtil;
48: import org.osgi.framework.ServiceReference;
49: import org.osgi.util.tracker.ServiceTracker;
50: import org.osgi.util.tracker.ServiceTrackerCustomizer;
51:
52: /**
53: * Util class for faking native widgets.
54: *
55: * @author jfaltermeier
56: *
57: */
58: public final class NativeWidgetHelper {
59:
60:         private static final String WS_CARBON = "carbon";//$NON-NLS-1$
61:         private static final String WS_COCOA = "cocoa";//$NON-NLS-1$
62:
63:         private static final String CHECKED_DEFAULT = "icons/checked.png"; //$NON-NLS-1$
64:         private static final String UNCHECKED_DEFAULT = "icons/unchecked.png"; //$NON-NLS-1$
65:
66:         private static final Lock LOCK = new ReentrantLock(true);
67:         private static boolean initalized;
68:
69:         private static final Bundle BUNDLE;
70:         private static final ServiceTracker<ImageRegistryService, ImageRegistryService> IMAGE_REGISTRY_SERVICE_TRACKER;
71:
72:         private static ImageData checked;
73:         private static ImageData unchecked;
74:
75:         private static Image defaultCheckedImage;
76:         private static Image defaultUncheckedImage;
77:
78:         static {
79:                 BUNDLE = FrameworkUtil.getBundle(NativeWidgetHelper.class);
80:                 IMAGE_REGISTRY_SERVICE_TRACKER = new ServiceTracker<>(BUNDLE.getBundleContext(), ImageRegistryService.class,
81:                         new ImageRegistryServiceCustomizer());
82:                 IMAGE_REGISTRY_SERVICE_TRACKER.open();
83:         }
84:
85:         private NativeWidgetHelper() {
86:                 // util
87:         }
88:
89:         /**
90:          * Creates screenshots of the platform's native checkbox in checked and unchecked state. The images can be accessed
91:          * via {@link NativeWidgetHelper#getCheckBoxImage(Control, CheckBoxState)}.
92:          *
93:          * @param control a control which provides the {@link org.eclipse.swt.widgets.Display Display} and {@link Shell} to
94:          * create the screen shots
95:          */
96:         public static void initCheckBoxImages(Control control) {
97:                 try {
98:                         LOCK.lock();
99:                         if (!initalized) {
100:                                 createCheckBoxImage(control, true);
101:                                 createCheckBoxImage(control, false);
102:                                 initalized = true;
103:                         }
104:                 } finally {
105:                         LOCK.unlock();
106:                 }
107:         }
108:
109:         /**
110:          * Returns the image of a checkbox. If {@link NativeWidgetHelper#initCheckBoxImages(Control)} was called beforehand
111:          * this will return images resembling the platform's native widgets. Otherwise a default image (Windows 7) will be
112:          * returned.
113:          *
114:          * @param control a control which provides the {@link org.eclipse.swt.widgets.Display Display} to create the image
115:          * @param state the state of the checkbox
116:          * @return the image
117:          */
118:         public static Image getCheckBoxImage(Control control, CheckBoxState state) {
119:                 try {
120:                         LOCK.lock();
121:                         switch (state) {
122:
123:                         case checked:
124:                                 if (checked != null) {
125:                                         return new Image(control.getDisplay(), checked);
126:                                 }
127:                                 return defaultCheckedImage;
128:                         case unchecked:
129:                                 if (unchecked != null) {
130:                                         return new Image(control.getDisplay(), unchecked);
131:                                 }
132:                                 return defaultUncheckedImage;
133:                         default:
134:                                 break;
135:
136:                         }
137:                 } finally {
138:                         LOCK.unlock();
139:                 }
140:
141:                 return null;
142:
143:         }
144:
145:         /**
146:          * <p>
147:          * Fills the image cache for checkboxes.
148:          * </p>
149:          * <p>
150:          * This is based on org.eclipse.jface.snippets.viewers.Snippet061FakedNativeCellEditor
151:          * </p>
152:          *
153:          * @param control the control
154:          * @param type <code>true</code> for checked state, <code>false</code> otherwise
155:          */
156:         private static void createCheckBoxImage(Control control, boolean type) {
157:                 // Hopefully no platform uses exactly this color because we'll make
158:                 // it transparent in the image.
159:
160:                 final Display display = Display.getDefault();
161:                 final Color greenScreen = new Color(display, 3, 223, 7);
162:
163:                 final Shell shell = new Shell(control.getShell());
164:                 ImageData imageData = null;
165:
166:                 // otherwise we have a default gray color
167:                 shell.setBackground(greenScreen);
168:
169:                 if (isMac()) {
170:                         final Button button2 = new Button(shell, SWT.CHECK);
171:                         final Point bsize = button2.computeSize(SWT.DEFAULT, SWT.DEFAULT);
172:
173:                         // otherwise an image is stretched by width
174:                         bsize.x = Math.max(bsize.x - 1, bsize.y - 1);
175:                         bsize.y = Math.max(bsize.x - 1, bsize.y - 1);
176:                         button2.setSize(bsize);
177:                         button2.setLocation(100, 100);
178:                 }
179:
180:                 final Button button = new Button(shell, SWT.CHECK);
181:                 button.setBackground(greenScreen);
182:                 button.setSelection(type);
183:
184:                 // otherwise an image is located in a corner
185:                 button.setLocation(1, 1);
186:                 final Point bsize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT);
187:
188:                 // otherwise an image is stretched by width
189:                 bsize.x = Math.max(bsize.x - 1, bsize.y - 1);
190:                 bsize.y = Math.max(bsize.x - 1, bsize.y - 1);
191:                 button.setSize(bsize);
192:
193:                 shell.setSize(bsize);
194:                 shell.setVisible(false);
195:
196:                 shell.open();
197:
198:                 final GC gc = new GC(shell);
199:                 final Image image = new Image(display, bsize.x, bsize.y);
200:                 gc.copyArea(image, 0, 0);
201:                 gc.dispose();
202:                 shell.close();
203:
204:                 imageData = image.getImageData();
205:                 imageData.transparentPixel = imageData.palette.getPixel(greenScreen
206:                         .getRGB());
207:
208:                 if (type) {
209:                         checked = imageData;
210:                 } else {
211:                         unchecked = imageData;
212:                 }
213:
214:                 image.dispose();
215:         }
216:
217:         private static boolean isMac() {
218:                 final String ws = SWT.getPlatform();
219:                 return WS_CARBON.equals(ws) || WS_COCOA.equals(ws);
220:         }
221:
222:         /**
223:          * Enum describing the state of a checkbox.
224:          *
225:          * @author jfaltermeier
226:          *
227:          */
228:         public enum CheckBoxState {
229:                 /**
230:                  * The enabled, visible, checked state.
231:                  */
232:                 checked,
233:
234:                 /**
235:                  * The enabled, visible, uncheched state.
236:                  */
237:                 unchecked
238:         }
239:
240:         /**
241:          * Service-tracker customizer that uses the image-registry service, when it is
242:          * discovered or updated, to get and cache the default checked and unchecked images.
243:          */
244:         private static final class ImageRegistryServiceCustomizer
245:                 implements ServiceTrackerCustomizer<ImageRegistryService, ImageRegistryService> {
246:
247:                 @Override
248:                 public ImageRegistryService addingService(ServiceReference<ImageRegistryService> reference) {
249:                         final ImageRegistryService result = BUNDLE.getBundleContext().getService(reference);
250:
251:                         onUI(() -> updateImages(result));
252:
253:                         return result;
254:                 }
255:
256:                 @Override
257:                 public void modifiedService(ServiceReference<ImageRegistryService> reference, ImageRegistryService service) {
258:                         onUI(() -> updateImages(service));
259:                 }
260:
261:                 @Override
262:                 public void removedService(ServiceReference<ImageRegistryService> reference, ImageRegistryService service) {
263:                         onUI(() -> updateImages(null));
264:                 }
265:
266:                 private void onUI(Runnable action) {
267:                         final Display display = Display.getCurrent();
268:•                        if (display != null) {
269:                                 action.run();
270:                         } else {
271:                                 Display.getDefault().syncExec(action);
272:                         }
273:                 }
274:
275:                 private void updateImages(ImageRegistryService imageRegistryService) {
276:                         LOCK.lock();
277:
278:                         try {
279:•                                if (imageRegistryService != null) {
280:                                         defaultCheckedImage = imageRegistryService.getImage(BUNDLE, CHECKED_DEFAULT);
281:                                         defaultUncheckedImage = imageRegistryService.getImage(BUNDLE, UNCHECKED_DEFAULT);
282:                                 } else {
283:                                         defaultCheckedImage = null;
284:                                         defaultUncheckedImage = null;
285:                                 }
286:                         } finally {
287:                                 LOCK.unlock();
288:                         }
289:                 }
290:         }
291: }