1 /******************************************************************************* 2 * Copyright (c) 2011 Google, Inc. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * Google, Inc. - initial API and implementation 10 *******************************************************************************/ 11 12 package org.eclipse.wb.internal.core; 13 14 import com.google.common.collect.Maps; 15 import com.google.common.io.CharStreams; 16 import com.google.common.io.Closeables; 17 18 import org.eclipse.core.runtime.IStatus; 19 import org.eclipse.core.runtime.Status; 20 import org.eclipse.jface.resource.ImageDescriptor; 21 import org.eclipse.swt.graphics.Image; 22 import org.eclipse.swt.widgets.Display; 23 import org.eclipse.swt.widgets.Shell; 24 import org.eclipse.ui.IWorkbenchWindow; 25 import org.eclipse.ui.plugin.AbstractUIPlugin; 26 27 import java.io.Closeable; 28 import java.io.InputStream; 29 import java.io.InputStreamReader; 30 import java.net.URL; 31 import java.nio.charset.Charset; 32 import java.util.Map; 33 34 /** 35 * The DesignerPlugin class is the "nexus" of the propertysheet. In WindowBuilder, 36 * it's the plugin activator, and contains a number of important utility methods, such 37 * as resource loading, logging, obtaining a display and shell, etc. 38 * <p> 39 * In the AOSP fork, most of the functionality has been ripped out, except for the 40 * above mentioned pieces, and this class is no longer a plugin. Instead, it *delegates* 41 * to the plugin which initializes it via the {@link #initialize} method for things 42 * like logging. For things like image loading, it has its own local code such that 43 * it can find its image resources locally instead of requiring the embedding plugin 44 * to copy the images into its own jar. 45 * <p> 46 * "DesignerPlugin" is not a very good name for this class since it is not a plugin, 47 * but it was left that way to avoid modifying all the various propertysheet classes; 48 * we'd like to keep those as unmodified as possible to make absorbing future 49 * WindowBuilder improvements as easy as possible. 50 */ 51 public class DesignerPlugin { 52 private static AbstractUIPlugin sPlugin; 53 private static String sPluginId; 54 55 /** 56 * Initialize the property sheet for use in the ADT plugin 57 * 58 * @param hostPlugin the plugin to embed the property sheet 59 * @param pluginId the id of the plugin to use in status messages etc 60 * @param isWindows whether we're running on Windows 61 * @param isMac whether we're running on Mac 62 * @param isLinux whether we're running on Linux 63 */ initialize(AbstractUIPlugin hostPlugin, String pluginId, boolean isWindows, boolean isMac, boolean isLinux)64 public static void initialize(AbstractUIPlugin hostPlugin, String pluginId, 65 boolean isWindows, boolean isMac, boolean isLinux) { 66 assert sPlugin == null; // Can only be used by one client in the same classloader 67 sPlugin = hostPlugin; 68 sPluginId = pluginId; 69 EnvironmentUtils.IS_WINDOWS = isWindows; 70 EnvironmentUtils.IS_MAC = isMac; 71 EnvironmentUtils.IS_LINUX = isLinux; 72 } 73 74 /** 75 * Dispose the propertysheet library: free up images from the cache, unregister the 76 * plugin reference etc. 77 */ dispose()78 public static void dispose() { 79 sPlugin = null; 80 for (Image image : sImageCache.values()) { 81 image.dispose(); 82 } 83 sImageCache.clear(); 84 sDescriptorCache.clear(); 85 } 86 87 /** 88 * Reads the contents of an {@link InputStreamReader} using the default 89 * platform encoding and return it as a String. This method will close the 90 * input stream. 91 * 92 * @param inputStream the input stream to be read from 93 * @param charset the charset to use 94 * @return the String read from the stream, or null if there was an error 95 */ readFile(InputStream inputStream, Charset charset)96 public static String readFile(InputStream inputStream, Charset charset) { 97 if (inputStream == null) { 98 return null; 99 } 100 Closeable closeMe = inputStream; 101 try { 102 final InputStreamReader isr = new InputStreamReader(inputStream, charset); 103 closeMe = isr; 104 try { 105 return CharStreams.toString(isr); 106 } catch (Exception ioe) { 107 // pass -- ignore files we can't read 108 return null; 109 } 110 } finally { 111 Closeables.closeQuietly(closeMe); 112 } 113 } 114 115 /** 116 * @return the instance of {@link DesignerPlugin} 117 */ getDefault()118 public static AbstractUIPlugin getDefault() { 119 assert sPlugin != null; 120 return sPlugin; 121 } 122 123 // ////////////////////////////////////////////////////////////////////////// 124 // 125 // Display/Shell 126 // 127 // ////////////////////////////////////////////////////////////////////////// 128 /** 129 * @return the {@link Display} instance, current (if in GUI thread) or 130 * default. 131 */ getStandardDisplay()132 public static Display getStandardDisplay() { 133 Display display = Display.getCurrent(); 134 if (display == null) { 135 display = Display.getDefault(); 136 } 137 return display; 138 } 139 140 /** 141 * @return the active {@link IWorkbenchWindow}. 142 */ getActiveWorkbenchWindow()143 public static IWorkbenchWindow getActiveWorkbenchWindow() { 144 return getDefault().getWorkbench().getActiveWorkbenchWindow(); 145 } 146 147 /** 148 * @return the {@link Shell} of active {@link IWorkbenchWindow}. 149 */ getShell()150 public static Shell getShell() { 151 if (getActiveWorkbenchWindow() != null) { 152 return getActiveWorkbenchWindow().getShell(); 153 } 154 return null; 155 } 156 157 /** 158 * Logs given {@link IStatus} into Eclipse .log. 159 */ log(IStatus status)160 public static void log(IStatus status) { 161 getDefault().getLog().log(status); 162 } 163 164 /** 165 * Logs {@link IStatus} with given message into Eclipse .log. 166 */ log(String message)167 public static void log(String message) { 168 log(new Status(IStatus.INFO, sPluginId, IStatus.INFO, message, null)); 169 } 170 171 /** 172 * Logs {@link IStatus} with given exception into Eclipse .log. 173 */ log(Throwable e)174 public static void log(Throwable e) { 175 Status status = new Status(IStatus.ERROR, sPluginId, "", e); 176 getDefault().getLog().log(status); 177 } 178 179 /** 180 * Logs {@link IStatus} with given message and exception into Eclipse .log. 181 */ log(String message, Throwable e)182 public static void log(String message, Throwable e) { 183 log(createStatus(message, e)); 184 } 185 186 /** 187 * Creates {@link IStatus} for given message and exception. 188 */ createStatus(String message, Throwable e)189 public static Status createStatus(String message, Throwable e) { 190 return new Status(IStatus.ERROR, "wb", IStatus.ERROR, message, e) { 191 @Override 192 public boolean isMultiStatus() { 193 return true; 194 } 195 }; 196 } 197 198 // ////////////////////////////////////////////////////////////////////////// 199 // 200 // Resources 201 // 202 // ////////////////////////////////////////////////////////////////////////// 203 private static Map<String, ImageDescriptor> sDescriptorCache = Maps.newHashMap(); 204 private static Map<String, Image> sImageCache = Maps.newHashMap(); 205 206 public static Image getImage(String path) { 207 Image image = sImageCache.get(path); 208 if (image == null) { 209 ImageDescriptor descriptor = getImageDescriptor(path); 210 if (descriptor != null) { 211 return descriptor.createImage(); 212 } 213 sImageCache.put(path, image); 214 } 215 return image; 216 } 217 218 public static ImageDescriptor getImageDescriptor(String path) { 219 ImageDescriptor descriptor = sDescriptorCache.get(path); 220 if (descriptor == null) { 221 URL url = DesignerPlugin.class.getResource("icons/" + path); //$NON-NLS-1$ 222 if (url != null) { 223 descriptor = ImageDescriptor.createFromURL(url); 224 sDescriptorCache.put(path, descriptor); 225 } 226 } 227 return descriptor; 228 } 229 } 230