001: /*******************************************************************************
002: * Copyright (c) 2002, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.cheatsheets;
011:
012: import java.io.File;
013: import java.io.FileInputStream;
014: import java.io.FileNotFoundException;
015: import java.io.FileOutputStream;
016: import java.io.IOException;
017: import java.io.InputStreamReader;
018: import java.io.OutputStreamWriter;
019: import java.net.URL;
020:
021: import javax.xml.parsers.DocumentBuilder;
022: import javax.xml.parsers.DocumentBuilderFactory;
023:
024: import org.eclipse.core.runtime.FileLocator;
025: import org.eclipse.core.runtime.IPath;
026: import org.eclipse.core.runtime.IStatus;
027: import org.eclipse.core.runtime.Path;
028: import org.eclipse.core.runtime.SafeRunner;
029: import org.eclipse.core.runtime.Status;
030: import org.eclipse.jface.resource.ImageDescriptor;
031: import org.eclipse.jface.resource.ImageRegistry;
032: import org.eclipse.jface.util.SafeRunnable;
033: import org.eclipse.swt.graphics.Image;
034: import org.eclipse.ui.IMemento;
035: import org.eclipse.ui.XMLMemento;
036: import org.eclipse.ui.internal.cheatsheets.registry.CheatSheetRegistryReader;
037: import org.eclipse.ui.plugin.AbstractUIPlugin;
038: import org.osgi.framework.Bundle;
039: import org.osgi.framework.BundleContext;
040:
041: /**
042: * The main plugin class for cheat sheets.
043: */
044:
045: public class CheatSheetPlugin extends AbstractUIPlugin {
046:
047: public final static String PLUGIN_ID = "org.eclipse.help.base"; //$NON-NLS-1$
048:
049: //The shared instance of this plugin.
050: static CheatSheetPlugin plugin;
051:
052: //Resource bundle.
053: //private boolean resourceBundleInitialized = false;
054: //private ResourceBundle resourceBundle;
055: private CheatSheetHistory history = null;
056: private DocumentBuilder documentBuilder = null;
057:
058: private static final String HISTORY_FILENAME = "history.xml"; //$NON-NLS-1$
059: private static final String MEMENTO_TAG_CHEATSHEET = "cheatsheet"; //$NON-NLS-1$
060: private static final String MEMENTO_TAG_VERSION = "version"; //$NON-NLS-1$
061: private static final String VERSION_STRING[] = { "0.0", "3.0.0" }; //$NON-NLS-1$ //$NON-NLS-2$
062: private static final String MEMENTO_TAG_CHEATSHEET_HISTORY = "cheatsheetHistory"; //$NON-NLS-1$
063:
064: public static final IPath ICONS_PATH = new Path("$nl$/icons/"); //$NON-NLS-1$
065: public static final String T_OBJ = "obj16/"; //$NON-NLS-1$
066: public static final String T_ELCL = "elcl16/"; //$NON-NLS-1$
067: public static final String T_DLCL = "dlcl16/"; //$NON-NLS-1$
068: public static final String T_VIEW = "view16/"; //$NON-NLS-1$
069:
070: /**
071: * The constructor.
072: */
073: public CheatSheetPlugin() {
074: super ();
075: }
076:
077: /**
078: * Returns the shared instance.
079: */
080: public static CheatSheetPlugin getPlugin() {
081: return plugin;
082: }
083:
084: /**
085: * Returns the image in Cheat Sheet's image registry with the given key,
086: * or <code>null</code> if none.
087: * Convenience method equivalent to
088: * <pre>
089: * CheatSheetPlugin.getImageRegistry().get(key)
090: * </pre>
091: *
092: * @param key the key
093: * @return the image, or <code>null</code> if none
094: */
095: public Image getImage(String key) {
096: Image image = getImageRegistry().get(key);
097: return image;
098: }
099:
100: /**
101: * Returns the CheatSheetHistory
102: */
103: public CheatSheetHistory getCheatSheetHistory() {
104: if (history == null) {
105: history = new CheatSheetHistory(CheatSheetRegistryReader
106: .getInstance());
107: restoreCheatSheetHistory();
108: }
109: return history;
110: }
111:
112: /**
113: * Get a file from the state folder.
114: */
115: private File getCheatSheetStateFile(String filename) {
116: IPath path = CheatSheetPlugin.getPlugin().getStateLocation();
117: path = path.append(filename);
118: return path.toFile();
119: }
120:
121: /**
122: * Returns the DocumentBuilder to be used by the cheat sheets.
123: */
124: public DocumentBuilder getDocumentBuilder() {
125: if (documentBuilder == null) {
126: try {
127: documentBuilder = DocumentBuilderFactory.newInstance()
128: .newDocumentBuilder();
129: } catch (Exception e) {
130: IStatus status = new Status(IStatus.ERROR,
131: ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID,
132: IStatus.OK,
133: Messages.ERROR_CREATING_DOCUMENT_BUILDER, e);
134: CheatSheetPlugin.getPlugin().getLog().log(status);
135: }
136: }
137: return documentBuilder;
138: }
139:
140: /**
141: * Logs an Error message with an exception.
142: */
143: public static synchronized void logError(String message,
144: Throwable ex) {
145: if (message == null)
146: message = ""; //$NON-NLS-1$
147: Status errorStatus = new Status(IStatus.ERROR, PLUGIN_ID,
148: IStatus.OK, message, ex);
149: CheatSheetPlugin.getPlugin().getLog().log(errorStatus);
150: }
151:
152: protected void initializeImageRegistry(ImageRegistry reg) {
153: IPath path = ICONS_PATH.append(T_OBJ).append(
154: "cheatsheet_obj.gif");//$NON-NLS-1$
155: ImageDescriptor imageDescriptor = createImageDescriptor(
156: getPlugin().getBundle(), path);
157: reg.put(ICheatSheetResource.CHEATSHEET_OBJ, imageDescriptor);
158:
159: path = ICONS_PATH.append(T_OBJ).append("skip_status.gif");//$NON-NLS-1$
160: imageDescriptor = createImageDescriptor(
161: getPlugin().getBundle(), path);
162: reg.put(ICheatSheetResource.CHEATSHEET_ITEM_SKIP,
163: imageDescriptor);
164:
165: path = ICONS_PATH.append(T_OBJ).append("complete_status.gif");//$NON-NLS-1$
166: imageDescriptor = createImageDescriptor(
167: getPlugin().getBundle(), path);
168: reg.put(ICheatSheetResource.CHEATSHEET_ITEM_COMPLETE,
169: imageDescriptor);
170:
171: path = ICONS_PATH.append(T_ELCL).append("linkto_help.gif");//$NON-NLS-1$
172: imageDescriptor = createImageDescriptor(
173: getPlugin().getBundle(), path);
174: reg.put(ICheatSheetResource.CHEATSHEET_ITEM_HELP,
175: imageDescriptor);
176:
177: path = ICONS_PATH.append(T_ELCL).append("start_cheatsheet.gif");//$NON-NLS-1$
178: imageDescriptor = createImageDescriptor(
179: getPlugin().getBundle(), path);
180: reg.put(ICheatSheetResource.CHEATSHEET_START, imageDescriptor);
181:
182: path = ICONS_PATH.append(T_ELCL).append(
183: "restart_cheatsheet.gif");//$NON-NLS-1$
184: imageDescriptor = createImageDescriptor(
185: getPlugin().getBundle(), path);
186: reg
187: .put(ICheatSheetResource.CHEATSHEET_RESTART,
188: imageDescriptor);
189:
190: path = ICONS_PATH.append(T_ELCL).append("start_task.gif");//$NON-NLS-1$
191: imageDescriptor = createImageDescriptor(
192: getPlugin().getBundle(), path);
193: reg.put(ICheatSheetResource.CHEATSHEET_ITEM_BUTTON_START,
194: imageDescriptor);
195:
196: path = ICONS_PATH.append(T_ELCL).append("skip_task.gif");//$NON-NLS-1$
197: imageDescriptor = createImageDescriptor(
198: getPlugin().getBundle(), path);
199: reg.put(ICheatSheetResource.CHEATSHEET_ITEM_BUTTON_SKIP,
200: imageDescriptor);
201:
202: path = ICONS_PATH.append(T_ELCL).append("complete_task.gif");//$NON-NLS-1$
203: imageDescriptor = createImageDescriptor(
204: getPlugin().getBundle(), path);
205: reg.put(ICheatSheetResource.CHEATSHEET_ITEM_BUTTON_COMPLETE,
206: imageDescriptor);
207:
208: path = ICONS_PATH.append(T_ELCL).append("restart_task.gif");//$NON-NLS-1$
209: imageDescriptor = createImageDescriptor(
210: getPlugin().getBundle(), path);
211: reg.put(ICheatSheetResource.CHEATSHEET_ITEM_BUTTON_RESTART,
212: imageDescriptor);
213:
214: path = ICONS_PATH.append(T_ELCL).append("return_to_start.gif");//$NON-NLS-1$
215: imageDescriptor = createImageDescriptor(
216: getPlugin().getBundle(), path);
217: reg.put(ICheatSheetResource.CHEATSHEET_RETURN, imageDescriptor);
218:
219: path = ICONS_PATH.append(T_OBJ).append("error.gif");//$NON-NLS-1$
220: imageDescriptor = createImageDescriptor(
221: getPlugin().getBundle(), path);
222: reg.put(ICheatSheetResource.ERROR, imageDescriptor);
223:
224: // Images used by composites
225:
226: path = ICONS_PATH.append(T_OBJ).append("composite_obj.gif");//$NON-NLS-1$
227: imageDescriptor = createImageDescriptor(
228: getPlugin().getBundle(), path);
229: reg.put(ICheatSheetResource.COMPOSITE_OBJ, imageDescriptor);
230:
231: path = ICONS_PATH.append(T_OBJ).append("information.gif");//$NON-NLS-1$
232: imageDescriptor = createImageDescriptor(
233: getPlugin().getBundle(), path);
234: reg.put(ICheatSheetResource.INFORMATION, imageDescriptor);
235:
236: path = ICONS_PATH.append(T_OBJ).append("warning.gif");//$NON-NLS-1$
237: imageDescriptor = createImageDescriptor(
238: getPlugin().getBundle(), path);
239: reg.put(ICheatSheetResource.WARNING, imageDescriptor);
240:
241: path = ICONS_PATH.append(T_ELCL).append("start_ccs_task.gif");//$NON-NLS-1$
242: imageDescriptor = createImageDescriptor(
243: getPlugin().getBundle(), path);
244: reg.put(ICheatSheetResource.COMPOSITE_TASK_START,
245: imageDescriptor);
246:
247: path = ICONS_PATH.append(T_ELCL).append("skip_ccs_task.gif");//$NON-NLS-1$
248: imageDescriptor = createImageDescriptor(
249: getPlugin().getBundle(), path);
250: reg.put(ICheatSheetResource.COMPOSITE_TASK_SKIP,
251: imageDescriptor);
252:
253: path = ICONS_PATH.append(T_ELCL).append("review_ccs_task.gif");//$NON-NLS-1$
254: imageDescriptor = createImageDescriptor(
255: getPlugin().getBundle(), path);
256: reg.put(ICheatSheetResource.COMPOSITE_TASK_REVIEW,
257: imageDescriptor);
258:
259: path = ICONS_PATH.append(T_ELCL).append("goto_ccs_task.gif");//$NON-NLS-1$
260: imageDescriptor = createImageDescriptor(
261: getPlugin().getBundle(), path);
262: reg.put(ICheatSheetResource.COMPOSITE_GOTO_TASK,
263: imageDescriptor);
264:
265: path = ICONS_PATH.append(T_ELCL).append("restart_all.gif");//$NON-NLS-1$
266: imageDescriptor = createImageDescriptor(
267: getPlugin().getBundle(), path);
268: reg.put(ICheatSheetResource.COMPOSITE_RESTART_ALL,
269: imageDescriptor);
270:
271: path = ICONS_PATH.append(T_VIEW).append("cheatsheet_view.gif");//$NON-NLS-1$
272: imageDescriptor = createImageDescriptor(
273: getPlugin().getBundle(), path);
274: reg.put(ICheatSheetResource.CHEATSHEET_VIEW, imageDescriptor);
275: }
276:
277: /**
278: * Restores the state of the previously saved cheatsheet history
279: */
280: private void restoreCheatSheetHistory() {
281: SafeRunner.run(new SafeRunnable() {
282: public void run() {
283: IMemento memento;
284: memento = readMemento(HISTORY_FILENAME);
285: if (memento != null) {
286: IMemento childMem = memento
287: .getChild(MEMENTO_TAG_CHEATSHEET_HISTORY);
288: if (childMem != null) {
289: history.restoreState(childMem);
290: }
291: }
292: }
293:
294: public void handleException(Throwable e) {
295: String message = Messages.ERROR_READING_STATE_FILE;
296: IStatus status = new Status(IStatus.ERROR,
297: ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID,
298: IStatus.OK, message, e);
299: CheatSheetPlugin.getPlugin().getLog().log(status);
300: }
301: });
302: }
303:
304: /**
305: * Read a memento from the state directory for the cheatsheets plugin
306: * @param filename A simple filename
307: * @return A memento read from the state directory or null if the memento could not be read
308: */
309: public XMLMemento readMemento(String filename) {
310: XMLMemento memento;
311: InputStreamReader reader = null;
312:
313: try {
314: // Read the cheatsheet state file.
315: final File stateFile = getCheatSheetStateFile(filename);
316:
317: FileInputStream input = new FileInputStream(stateFile);
318: reader = new InputStreamReader(input, "utf-8"); //$NON-NLS-1$
319: memento = XMLMemento.createReadRoot(reader);
320:
321: } catch (FileNotFoundException e) {
322: memento = null;
323: // Do nothing, the file will not exist the first time the workbench in used.
324: } catch (Exception e) {
325: String message = Messages.ERROR_READING_STATE_FILE;
326: IStatus status = new Status(IStatus.ERROR,
327: ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID,
328: IStatus.OK, message, e);
329: CheatSheetPlugin.getPlugin().getLog().log(status);
330: memento = null;
331: } finally {
332: try {
333: if (reader != null)
334: reader.close();
335: } catch (IOException e) {
336: // Not much to do, just catch the exception and keep going.
337: String message = Messages.ERROR_READING_STATE_FILE;
338: IStatus status = new Status(IStatus.ERROR,
339: ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID,
340: IStatus.OK, message, e);
341: CheatSheetPlugin.getPlugin().getLog().log(status);
342: }
343: }
344: return memento;
345: }
346:
347: /**
348: * Saves the current cheatsheet history so it can be restored later on
349: */
350: private void saveCheatSheetHistory() {
351: SafeRunner.run(new SafeRunnable() {
352: public void run() {
353: XMLMemento memento = XMLMemento
354: .createWriteRoot(MEMENTO_TAG_CHEATSHEET);
355:
356: // Save the version number.
357: memento.putString(MEMENTO_TAG_VERSION,
358: VERSION_STRING[1]);
359:
360: // Save perspective history.
361: getCheatSheetHistory()
362: .saveState(
363: memento
364: .createChild(MEMENTO_TAG_CHEATSHEET_HISTORY));
365:
366: IStatus status = saveMemento(memento, HISTORY_FILENAME);
367: if (!status.isOK()) {
368: CheatSheetPlugin.getPlugin().getLog().log(status);
369: }
370: }
371:
372: public void handleException(Throwable e) {
373: String message = Messages.ERROR_WRITING_STATE_FILE;
374: IStatus status = new Status(IStatus.ERROR,
375: ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID,
376: IStatus.OK, message, e);
377: CheatSheetPlugin.getPlugin().getLog().log(status);
378: }
379: });
380: }
381:
382: /**
383: * Save the memento to a file in this plugins state area
384: * @param memento The memento to save
385: * @param filename A simple filename
386: * @return OK_Status if the memento was saved without error, otherwise an error
387: * status
388: */
389: public IStatus saveMemento(XMLMemento memento, String filename) {
390: // Save the IMemento to a file.
391: File stateFile = getCheatSheetStateFile(filename);
392: OutputStreamWriter writer = null;
393: try {
394: FileOutputStream stream = new FileOutputStream(stateFile);
395: writer = new OutputStreamWriter(stream, "utf-8"); //$NON-NLS-1$
396: memento.save(writer);
397: return Status.OK_STATUS;
398: } catch (IOException e) {
399: stateFile.delete();
400: String message = Messages.ERROR_WRITING_STATE_FILE;
401: IStatus status = new Status(IStatus.ERROR,
402: ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID,
403: IStatus.OK, message, e);
404: return status;
405: } finally {
406: try {
407: if (writer != null)
408: writer.close();
409: } catch (IOException e) {
410: String message = Messages.ERROR_WRITING_STATE_FILE;
411: IStatus status = new Status(IStatus.ERROR,
412: ICheatSheetResource.CHEAT_SHEET_PLUGIN_ID,
413: IStatus.OK, message, e);
414: CheatSheetPlugin.getPlugin().getLog().log(status);
415: }
416: }
417: }
418:
419: /* (non-Javadoc)
420: * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
421: */
422: public void start(BundleContext context) throws Exception {
423: super .start(context);
424:
425: plugin = this ;
426:
427: // allow the MRU history to be lazily initialized by getCheatSheetHistory
428: }
429:
430: /* (non-Javadoc)
431: * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
432: */
433: public void stop(BundleContext context) throws Exception {
434: super .stop(context);
435:
436: // save the MRU history if necessary
437: // if we never restored history, let existing memento stand
438: if (history != null) {
439: saveCheatSheetHistory();
440: }
441:
442: CheatSheetRegistryReader.getInstance().stop();
443: }
444:
445: /*
446: * Since 3.1.1. Load from icon paths with $NL$
447: */
448: public static ImageDescriptor createImageDescriptor(Bundle bundle,
449: IPath path) {
450: URL url = FileLocator.find(bundle, path, null);
451: if (url != null) {
452: return ImageDescriptor.createFromURL(url);
453: }
454: return null;
455: }
456:
457: }
|