1 
2 package $packageName$;
3 
4 import java.util.ArrayList;
5 import java.util.Iterator;
6 
7 import org.eclipse.core.runtime.IConfigurationElement;
8 import org.eclipse.core.runtime.IExtension;
9 import org.eclipse.core.runtime.Platform;
10 import org.eclipse.jface.resource.ImageDescriptor;
11 import org.eclipse.swt.SWT;
12 import org.eclipse.swt.graphics.Image;
13 import org.eclipse.swt.graphics.Point;
14 import org.eclipse.swt.layout.GridLayout;
15 import org.eclipse.swt.widgets.Composite;
16 import org.eclipse.swt.widgets.Label;
17 import org.eclipse.swt.widgets.Shell;
18 import org.eclipse.ui.plugin.AbstractUIPlugin;
19 import org.eclipse.ui.splash.AbstractSplashHandler;
20 
21 /**
22  * @since 3.3
23  *
24  */
25 public class ExtensibleSplashHandler extends AbstractSplashHandler {
26 
27 	private ArrayList fImageList;
28 
29 	private ArrayList fTooltipList;
30 
31 	private final static String F_SPLASH_EXTENSION_ID = "$pluginId$.splashExtension"; //$NON-NLS-1$
32 
33 	private final static String F_ELEMENT_ICON = "icon"; //$NON-NLS-1$
34 
35 	private final static String F_ELEMENT_TOOLTIP = "tooltip"; //$NON-NLS-1$
36 
37 	private final static String F_DEFAULT_TOOLTIP = "Image"; //$NON-NLS-1$
38 
39 	private final static int F_IMAGE_WIDTH = 50;
40 
41 	private final static int F_IMAGE_HEIGHT = 50;
42 
43 	private final static int F_SPLASH_SCREEN_BEVEL = 5;
44 
45 	private Composite fIconPanel;
46 
47 	/**
48 	 *
49 	 */
ExtensibleSplashHandler()50 	public ExtensibleSplashHandler() {
51 		fImageList = new ArrayList();
52 		fTooltipList = new ArrayList();
53 		fIconPanel = null;
54 	}
55 
56 	/* (non-Javadoc)
57 	 * @see org.eclipse.ui.splash.AbstractSplashHandler#init(org.eclipse.swt.widgets.Shell)
58 	 */
init(Shell splash)59 	public void init(Shell splash) {
60 		// Store the shell
61 		super.init(splash);
62 		// Configure the shell layout
63 		configureUISplash();
64 		// Load all splash extensions
65 		loadSplashExtensions();
66 		// If no splash extensions were loaded abort the splash handler
67 		if (hasSplashExtensions() == false) {
68 			return;
69 		}
70 		// Create UI
71 		createUI();
72 		// Configure the image panel bounds
73 		configureUICompositeIconPanelBounds();
74 		// Enter event loop and prevent the RCP application from
75 		// loading until all work is done
76 		doEventLoop();
77 	}
78 
79 	/**
80 	 * @return
81 	 */
hasSplashExtensions()82 	private boolean hasSplashExtensions() {
83 		if (fImageList.isEmpty()) {
84 			return false;
85 		} else {
86 			return true;
87 		}
88 	}
89 
90 	/**
91 	 *
92 	 */
createUI()93 	private void createUI() {
94 		// Create the icon panel
95 		createUICompositeIconPanel();
96 		// Create the images
97 		createUIImages();
98 	}
99 
100 	/**
101 	 *
102 	 */
createUIImages()103 	private void createUIImages() {
104 		Iterator imageIterator = fImageList.iterator();
105 		Iterator tooltipIterator = fTooltipList.iterator();
106 		int i = 1;
107 		int columnCount = ((GridLayout)fIconPanel.getLayout()).numColumns;
108 		// Create all the images
109 		// Abort if we run out of columns (left-over images will not fit within
110 		// the usable splash screen width)
111 		while (imageIterator.hasNext() &&
112 				(i <= columnCount)) {
113 			Image image = (Image)imageIterator.next();
114 			String tooltip = (String)tooltipIterator.next();
115 			// Create the image using a label widget
116 			createUILabel(image, tooltip);
117 			i++;
118 		}
119 	}
120 
121 	/**
122 	 * @param image
123 	 * @param tooltip
124 	 */
createUILabel(Image image, String tooltip)125 	private void createUILabel(Image image, String tooltip) {
126 		// Create the label (no text)
127 		Label label = new Label(fIconPanel, SWT.NONE);
128 		label.setImage(image);
129 		label.setToolTipText(tooltip);
130 	}
131 
132 	/**
133 	 *
134 	 */
createUICompositeIconPanel()135 	private void createUICompositeIconPanel() {
136 		Shell splash = getSplash();
137 		// Create the composite
138 		fIconPanel = new Composite(splash, SWT.NONE);
139 		// Determine the maximum number of columns that can fit on the splash
140 		// screen.  One 50x50 image per column.
141 		int maxColumnCount = getUsableSplashScreenWidth() / F_IMAGE_WIDTH;
142 		// Limit size to the maximum number of columns if the number of images
143 		// exceed this amount; otherwise, use the exact number of columns
144 		// required.
145 		int actualColumnCount = Math.min(fImageList.size(), maxColumnCount);
146 		// Configure the layout
147 		GridLayout layout = new GridLayout(actualColumnCount, true);
148 		layout.horizontalSpacing = 0;
149 		layout.verticalSpacing = 0;
150 		layout.marginHeight = 0;
151 		layout.marginWidth = 0;
152 		fIconPanel.setLayout(layout);
153 	}
154 
155 	/**
156 	 *
157 	 */
configureUICompositeIconPanelBounds()158 	private void configureUICompositeIconPanelBounds() {
159 		// Determine the size of the panel and position it at the bottom-right
160 		// of the splash screen.
161 		Point panelSize = fIconPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
162 
163 		int x_coord = getSplash().getSize().x - F_SPLASH_SCREEN_BEVEL - panelSize.x;
164 		int y_coord = getSplash().getSize().y - F_SPLASH_SCREEN_BEVEL - panelSize.y;
165 		int x_width = panelSize.x;
166 		int y_width = panelSize.y;
167 
168 		fIconPanel.setBounds(x_coord, y_coord, x_width, y_width);
169 	}
170 
171 	/**
172 	 * @return
173 	 */
getUsableSplashScreenWidth()174 	private int getUsableSplashScreenWidth() {
175 		// Splash screen width minus two graphic border bevel widths
176 		return getSplash().getSize().x - (F_SPLASH_SCREEN_BEVEL * 2);
177 	}
178 
179 	/**
180 	 *
181 	 */
loadSplashExtensions()182 	private void loadSplashExtensions() {
183 		// Get all splash handler extensions
184 		IExtension[] extensions =
185 			Platform.getExtensionRegistry().getExtensionPoint(
186 					F_SPLASH_EXTENSION_ID).getExtensions();
187 		// Process all splash handler extensions
188 		for (int i = 0; i < extensions.length; i++) {
189 			processSplashExtension(extensions[i]);
190 		}
191 	}
192 
193 	/**
194 	 * @param extension
195 	 */
processSplashExtension(IExtension extension)196 	private void processSplashExtension(IExtension extension) {
197 		// Get all splash handler configuration elements
198 		IConfigurationElement[] elements = extension.getConfigurationElements();
199 		// Process all splash handler configuration elements
200 		for (int j = 0; j < elements.length; j++) {
201 			processSplashElements(elements[j]);
202 		}
203 	}
204 
205 	/**
206 	 * @param configurationElement
207 	 */
processSplashElements( IConfigurationElement configurationElement)208 	private void processSplashElements(
209 			IConfigurationElement configurationElement) {
210 		// Attribute: icon
211 		processSplashElementIcon(configurationElement);
212 		// Attribute: tooltip
213 		processSplashElementTooltip(configurationElement);
214 	}
215 
216 	/**
217 	 * @param configurationElement
218 	 */
processSplashElementTooltip( IConfigurationElement configurationElement)219 	private void processSplashElementTooltip(
220 			IConfigurationElement configurationElement) {
221 		// Get attribute tooltip
222 		String tooltip = configurationElement.getAttribute(F_ELEMENT_TOOLTIP);
223 		// If a tooltip is not defined, give it a default
224 		if ((tooltip == null) ||
225 				(tooltip.length() == 0)) {
226 			fTooltipList.add(F_DEFAULT_TOOLTIP);
227 		} else {
228 			fTooltipList.add(tooltip);
229 		}
230 	}
231 
232 	/**
233 	 * @param configurationElement
234 	 */
processSplashElementIcon( IConfigurationElement configurationElement)235 	private void processSplashElementIcon(
236 			IConfigurationElement configurationElement) {
237 		// Get attribute icon
238 		String iconImageFilePath = configurationElement.getAttribute(F_ELEMENT_ICON);
239 		// Abort if an icon attribute was not specified
240 		if ((iconImageFilePath == null) ||
241 				(iconImageFilePath.length() == 0)) {
242 			return;
243 		}
244 		// Create a corresponding image descriptor
245 		ImageDescriptor descriptor =
246 			AbstractUIPlugin.imageDescriptorFromPlugin(
247 					configurationElement.getNamespaceIdentifier(),
248 					iconImageFilePath);
249 		// Abort if no corresponding image was found
250 		if (descriptor == null) {
251 			return;
252 		}
253 		// Create the image
254 		Image image = descriptor.createImage();
255 		// Abort if image creation failed
256 		if (image == null) {
257 			return;
258 		}
259 		// Abort if the image does not have dimensions of 50x50
260 		if ((image.getBounds().width != F_IMAGE_WIDTH) ||
261 				(image.getBounds().height != F_IMAGE_HEIGHT)) {
262 			// Dipose of the image
263 			image.dispose();
264 			return;
265 		}
266 		// Store the image and tooltip
267 		fImageList.add(image);
268 	}
269 
270 	/**
271 	 *
272 	 */
configureUISplash()273 	private void configureUISplash() {
274 		// Configure layout
275 		GridLayout layout = new GridLayout(1, true);
276 		getSplash().setLayout(layout);
277 		// Force shell to inherit the splash background
278 		getSplash().setBackgroundMode(SWT.INHERIT_DEFAULT);
279 	}
280 
281 	/**
282 	 *
283 	 */
doEventLoop()284 	private void doEventLoop() {
285 		Shell splash = getSplash();
286 		if (splash.getDisplay().readAndDispatch() == false) {
287 			splash.getDisplay().sleep();
288 		}
289 	}
290 
291 	/* (non-Javadoc)
292 	 * @see org.eclipse.ui.splash.AbstractSplashHandler#dispose()
293 	 */
dispose()294 	public void dispose() {
295 		super.dispose();
296 		// Check to see if any images were defined
297 		if ((fImageList == null) ||
298 				fImageList.isEmpty()) {
299 			return;
300 		}
301 		// Dispose of all the images
302 		Iterator iterator = fImageList.iterator();
303 		while (iterator.hasNext()) {
304 			Image image = (Image) iterator.next();
305 			image.dispose();
306 		}
307 	}
308 }
309