Java tutorial
/******************************************************************************* * Copyright (c) 2005-2012 Synopsys, Incorporated * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Synopsys, Inc - Initial implementation *******************************************************************************/ package com.arc.cdt.debug.seecode.ui; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Set; import org.eclipse.cdt.debug.core.cdi.model.ICDITarget; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IAdapterManager; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; import com.arc.cdt.debug.seecode.core.ICustomDisplayCallbackCreator; import com.arc.cdt.debug.seecode.core.IDisplayMessage; import com.arc.cdt.debug.seecode.core.ILicenseExpirationChecker; import com.arc.cdt.debug.seecode.core.ILicenseFailure; import com.arc.cdt.debug.seecode.core.ISeeCodeConstants; import com.arc.cdt.debug.seecode.core.IStatusWriter; import com.arc.cdt.debug.seecode.core.SeeCodePlugin; import com.arc.cdt.debug.seecode.internal.ui.PromptForEngineSelectionDialog; import com.arc.cdt.debug.seecode.internal.ui.SeeCodeAdapterFactory; import com.arc.cdt.debug.seecode.internal.ui.SeeCodeMenuBarManager; import com.arc.cdt.debug.seecode.internal.ui.action.AnimateToolBarManager; import com.arc.cdt.debug.seecode.ui.display.CustomDisplayCallback; import com.arc.cdt.debug.seecode.ui.termsim.TermSimInstantiator; import com.arc.cdt.debug.seecode.ui.views.AbstractEngineBasedView; import com.arc.cdt.debug.seecode.ui.views.SeeCodeCustomView; import com.arc.cdt.debug.seecode.ui.views.SeeCodeDisasmView; import com.arc.debugger.IEngineResolver; import com.arc.seecode.display.IColorPreferences; import com.arc.seecode.engine.EngineInterface; import com.arc.seecode.engine.ICustomDisplayCallback; import com.arc.seecode.engine.IRunner; import com.arc.seecode.engine.ITimeoutCallback; import com.arc.widgets.IColor; import com.arc.widgets.IComponentFactory; import com.arc.widgets.WidgetsFactory; /** * The main plugin class to be used in the desktop. */ public class UISeeCodePlugin extends AbstractUIPlugin { public static final String PLUGIN_ID = "com.arc.cdt.debug.seecode.ui"; //The shared instance. private static UISeeCodePlugin plugin; //Resource bundle. private ResourceBundle resourceBundle; private static IComponentFactory sWidgetFactory = null; private SeeCodeMenuBarManager mMenuBarManager; private transient int mAlertDays; // days remaining to alert private AnimateToolBarManager fAnimateToolBarMgr; // /** // * The number of SeeCode processes running // */ // private static int sSeeCodeProcesses = 0; // /** * The constructor. */ public UISeeCodePlugin() { super(); plugin = this; try { resourceBundle = ResourceBundle.getBundle("com.arc.cdt.debug.seecode.ui.SeeCode"); } catch (MissingResourceException x) { resourceBundle = null; } // // Create the object that intercepts "create-display" // // events from the core plugin so as to create // // the Custom seecode displays. // new DisplayCreatorDelegate(); // The core plugin doesn't "see" us to avoid // circular dependencies. But it needs to // instantiate the CustomDisplayCallback class // that is defined in this package. // We use a callback to do that: SeeCodePlugin.getDefault().setCustomDisplayCallbackCreator(new ICustomDisplayCallbackCreator() { @Override public ICustomDisplayCallback create(ICDITarget target) { return new CustomDisplayCallback(target); } }); SeeCodePlugin.getDefault().setLicenseExpirationChecker(new ILicenseExpirationChecker() { @Override public void checkLicenseExpiration(int days) { UISeeCodePlugin.this.checkLicensingAlert(days); } }); SeeCodePlugin.getDefault().setLicensingFailure(new ILicenseFailure() { @Override public void reportLicenseFailure(final String msg) { PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { @Override public void run() { Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); String fullMsg = "A valid license for " + UISeeCodePlugin.getTheDebuggerName() + " was not found.\n\n" + msg; IStatus status = makeErrorStatus(fullMsg); ErrorDialog.openError(shell, UISeeCodePlugin.getDebuggerName() + " Licensing Failure", null, status); } }); } }); SeeCodePlugin.getDefault().setStatusWriter(new IStatusWriter() { @Override public void setStatus(final String msg) { // We need to get to the status line manager, but we can only get // access to from a viewsite. Unfortunately, we have // no direct reference to such. Therefore, look for // the debug view whose ID is "org.eclipse.debug.ui.DebugView" PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { @Override public void run() { IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (window != null) { IWorkbenchPage page = window.getActivePage(); if (page != null) { IViewPart viewPart = page.findView(IDebugUIConstants.ID_DEBUG_VIEW); if (viewPart != null) { IStatusLineManager statusLine = viewPart.getViewSite().getActionBars() .getStatusLineManager(); statusLine.setMessage(msg); } } } } }); } }); SeeCodePlugin.getDefault().setTermSimInstantiator(new TermSimInstantiator()); SeeCodePlugin.getDefault().setDisplayError(new IDisplayMessage() { @Override public void displayError(final String title, final String msg) { PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { @Override public void run() { showError(title, msg); } }); } @Override public void displayNote(final String title, final String msg) { PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { @Override public void run() { showNote(title, msg); } }); } }); SeeCodePlugin.getDefault().setEngineVersionStrategyCallback(new IEngineResolver() { @Override public boolean useToolSetEngine(final int bundledEngineId, final int toolsetEngineId, final String toolsetPath) { switch (SeeCodePlugin.getDefault().getPreferences().getInt( ISeeCodeConstants.PREF_ENGINE_VERSION_MANAGEMENT, ISeeCodeConstants.ENGINE_VERSION_USE_TOOLSET)) { case ISeeCodeConstants.ENGINE_VERSION_PROMPT: if (bundledEngineId != toolsetEngineId) { final boolean results[] = new boolean[1]; PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { @Override public void run() { results[0] = new PromptForEngineSelectionDialog( PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), bundledEngineId, toolsetEngineId, toolsetPath).open(); } }); return results[0]; } return false; case ISeeCodeConstants.ENGINE_VERSION_USE_BUNDLED: return false; case ISeeCodeConstants.ENGINE_VERSION_USE_TOOLSET: return true; case ISeeCodeConstants.ENGINE_VERSION_USE_LATEST: return toolsetEngineId > bundledEngineId; } return false; // shouldn't get here } }); /* SeeCodePlugin.getDefault().setProgramLoadTimeoutCallback(new IDiagnoseProgramLoadTimeout(){ public void diagnoseTimeout (final String exeName, final int timeout) { PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { public void run () { Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); String fullMsg = "The debugger engine timed out while loading\n\"" + exeName + "\".\n" + "The current timeout for loading a program is " + timeout + " milliseconds.\n" + "If you have a slow target connection, or if you are doing a long-running\n"+ "blast operation, you may need to increase the timeout value. Go to the\n" + "preference page: \"Windows->Preferences->C/C++->Debugger->MetaWare Debugger\".\n"; IStatus status = SeeCodePlugin.makeErrorStatus(fullMsg); ErrorDialog.openError(shell, "Program load timeout failure", null, status); } }); }});*/ SeeCodePlugin.getDefault().setLoadTimeoutCallback(new ITimeoutCallback() { private int _newTimeout = 0; @Override public int getNewTimeout(final int timeout) { PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { @Override public void run() { Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); String fullMsg = "The debugger engine is attempting to load a program and it has not\n" + "completed after \"" + (timeout + 500) / 1000 + "\" seconds (as specified in the " + "MetaWare Debugger\npreferences page).\n\n" + "If you are loading over a slow connnection, or if you are doing a blast\n" + "operation, the engine may need more time.\n\n" + "What do you want the IDE to do?\n"; MessageDialog dialog = new MessageDialog(shell, "Engine Timeout Alert", null, // accept fullMsg, MessageDialog.WARNING, new String[] { IDialogConstants.OK_LABEL }, 0) { @Override protected Control createCustomArea(Composite parent) { Composite container = new Group(parent, 0); container.setLayout(new GridLayout(4, false)); GridData gd = new GridData(); gd.horizontalSpan = 1; gd.grabExcessHorizontalSpace = false; final Button b1 = new Button(container, SWT.RADIO); b1.setLayoutData(gd); b1.setText("Wait no longer;"); // Label on button appears to be limited in size; add additional // as a label Label label1 = new Label(container, SWT.LEFT); label1.setText("abort if load is not yet complete."); GridData gd1 = new GridData(); gd1.horizontalSpan = 3; gd1.grabExcessHorizontalSpace = true; label1.setLayoutData(gd1); gd = new GridData(); gd.horizontalSpan = 4; gd.grabExcessHorizontalSpace = true; final Button b2 = new Button(container, SWT.RADIO); b2.setLayoutData(gd); b2.setText("Continue waiting indefinitely."); final Button b3 = new Button(container, SWT.RADIO); b3.setText("Wait for an additional number of seconds"); b3.setLayoutData(gd); final Label label = new Label(container, SWT.LEFT); label.setText(" Number of additional seconds to wait: "); gd = new GridData(); gd.horizontalSpan = 2; label.setLayoutData(gd); final Text field = new Text(container, SWT.SINGLE); field.setText("" + (timeout + 500) / 1000); gd = new GridData(); gd.horizontalSpan = 2; gd.grabExcessHorizontalSpace = true; gd.minimumWidth = 80; field.setLayoutData(gd); SelectionListener listener = new SelectionListener() { @Override public void widgetDefaultSelected(SelectionEvent e) { } @Override public void widgetSelected(SelectionEvent e) { if (e.widget == b1) { _newTimeout = 0; field.setEnabled(false); label.setEnabled(false); } else if (e.widget == b2) { _newTimeout = -1; field.setEnabled(false); label.setEnabled(false); } else { field.setEnabled(true); label.setEnabled(true); try { _newTimeout = Integer.parseInt(field.getText()) * 1000; } catch (NumberFormatException e1) { field.setText("0"); _newTimeout = 0; } } } }; b1.addSelectionListener(listener); b2.addSelectionListener(listener); b3.addSelectionListener(listener); field.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { try { if (b3.getSelection()) { _newTimeout = Integer.parseInt(field.getText()) * 1000; if (_newTimeout < 0) { field.setText("0"); _newTimeout = 0; } } } catch (NumberFormatException e1) { field.setText("0"); _newTimeout = 0; } } }); return container; } }; if (dialog.open() != Window.OK) { _newTimeout = 0; // terminate immediately. } } }); return _newTimeout; } }); /* * Set the Run wrapper for all engine callbacks so that they are in the UI thread. */ SeeCodePlugin.getDefault().setCallbackRunner(new IRunner() { @Override public void invoke(Runnable run, boolean async) throws Throwable { Display display = PlatformUI.getWorkbench().getDisplay(); try { // Run asynchronously to avoid deadlock of UI thread is // waiting for the engine to return. // display is null or disposed after workbench has shutdown, // but the engine may still be sending stuff... if (display != null && !display.isDisposed()) { if (async) { display.asyncExec(run); } else display.syncExec(run); } } catch (SWTException e) { if (e.throwable != null) { // If the display is disposed of after the above // check, but before the "run" is invoked, then // we can get an exception. Ignore such cases. if (display != null && !display.isDisposed()) throw e.throwable; } throw e; } } }); } private void checkLicensingAlert(final int daysRemaining) { final int alertDays = SeeCodePlugin.getDefault().getPreferences().getInt( ISeeCodeConstants.PREF_LICENSE_EXPIRATION_DAYS, ISeeCodeConstants.DEF_PREF_LICENSE_EXPIRATION_DAYS); if (daysRemaining >= 0) { boolean alert = SeeCodePlugin.getDefault().getPreferences() .getBoolean(ISeeCodeConstants.PREF_LICENSE_EXPIRATION_ALERT, true); if (alertDays >= daysRemaining) { if (alert) { PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { @Override public void run() { Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); String s; if (daysRemaining == 0) s = "after today"; else if (daysRemaining == 1) s = "after tomorrow"; else s = "in " + daysRemaining + " days"; MessageDialog dialog = new MessageDialog(shell, "License Expiration Alert", null, // accept "Debugger license will expire " + s, MessageDialog.WARNING, new String[] { IDialogConstants.OK_LABEL }, 0) { @Override protected Control createCustomArea(Composite parent) { if (daysRemaining > 0 && daysRemaining <= 2) { Label label = new Label(parent, SWT.RIGHT); GridData data = new GridData(); data.horizontalAlignment = GridData.END; data.grabExcessHorizontalSpace = true; label.setLayoutData(data); label.setText("You will be reminded again tomorrow."); setAlertDays(daysRemaining - 1); return label; } if (daysRemaining > 0) { Composite container = new Composite(parent, 0); GridData data = new GridData(); data.horizontalAlignment = GridData.END; data.grabExcessHorizontalSpace = true; container.setLayoutData(data); container.setLayout(new GridLayout(3, false)); Label label1 = new Label(container, SWT.LEFT); label1.setText("Remind me again when "); final Combo combo = new Combo(container, SWT.DROP_DOWN | SWT.READ_ONLY); Label label2 = new Label(container, SWT.LEFT); label2.setText(" days remain."); label2.setLayoutData(data); for (int i = Math.min(15, daysRemaining - 1); i >= 0; i--) { combo.add("" + i); } combo.select(0); setAlertDays(Integer.parseInt(combo.getItem(0))); combo.addSelectionListener(new SelectionListener() { @Override public void widgetDefaultSelected(SelectionEvent e) { } @Override public void widgetSelected(SelectionEvent e) { setAlertDays(Integer.parseInt(combo.getText())); } }); return container; } return null; } }; if (dialog.open() == Window.OK) { SeeCodePlugin.getDefault().getPreferences() .putInt(ISeeCodeConstants.PREF_LICENSE_EXPIRATION_DAYS, mAlertDays); } } }); } } else if (daysRemaining > ISeeCodeConstants.DEF_PREF_LICENSE_EXPIRATION_DAYS && alertDays != ISeeCodeConstants.DEF_PREF_LICENSE_EXPIRATION_DAYS) { // License has been renewed. Reset things to default. restoreDefaultAlertDays(); } } else if (alertDays != ISeeCodeConstants.DEF_PREF_LICENSE_EXPIRATION_DAYS) { // Evidently a permanent license; make sure we reset alert if he previously // had an expired one. restoreDefaultAlertDays(); } } private void restoreDefaultAlertDays() { // If license has been refreshed, then reset counter to default SeeCodePlugin.getDefault().getPreferences().putInt(ISeeCodeConstants.PREF_LICENSE_EXPIRATION_DAYS, ISeeCodeConstants.DEF_PREF_LICENSE_EXPIRATION_DAYS); } private void setAlertDays(int days) { mAlertDays = days; } /** * Returns the shared instance. */ public static UISeeCodePlugin getDefault() { return plugin; } /** * Returns the string from the plugin's resource bundle, or 'key' if not found. */ public static String getResourceString(String key) { ResourceBundle bundle = UISeeCodePlugin.getDefault().getResourceBundle(); try { return (bundle != null) ? bundle.getString(key) : key; } catch (MissingResourceException e) { return key; } } /** * Return whether or not this IDE is named "TopSide". * @return whether or not this IDE is named "TopSide". */ private static boolean isTopSide() { return System.getProperty("TOPSIDE") != null; } /** * * @return either "SeeCode" or "MetaWare Debugger" */ public static String getDebuggerName() { if (isTopSide()) { return "SeeCode"; } return "MetaWare Debugger"; } /** * * @return either "SeeCode" or "the MetaWare Debugger" */ public static String getTheDebuggerName() { return isTopSide() ? "SeeCode" : "the MetaWare Debugger"; } /** * Factory for creating our GUI-independent widgets * that our custom display framework uses. * @return the widget factory. */ public static IComponentFactory getWidgetFactory() { if (sWidgetFactory == null) { sWidgetFactory = WidgetsFactory.createSWT(PlatformUI.getWorkbench().getDisplay()); } return sWidgetFactory; } /** * Returns the plugin's resource bundle, */ public ResourceBundle getResourceBundle() { return resourceBundle; } public IMenuBarUpdater getMenuBarUpdater() { // Create object to control the seecode menu // in the main menu bar. // Must be created lazily, because the workbench may not be up // when this plugin is started. if (mMenuBarManager == null) mMenuBarManager = new SeeCodeMenuBarManager(); return mMenuBarManager; } /** * Map a SeeCode display "kind" to a CDT view that we have userped. */ private static final Map<String, String> sUserpedDisplayMap = new HashMap<String, String>(); static { sUserpedDisplayMap.put("reg", "org.eclipse.cdt.debug.ui.RegisterView"); sUserpedDisplayMap.put("disasm", SeeCodeDisasmView.DISASM_VIEW_ID); } /** * The set of display kinds that we permit more than one instance of. * E.g., Memory display. */ private static final Set<String> sRepeatableDisplays = new HashSet<String>(); static { sRepeatableDisplays.add("mem"); } /** * Given a display kind that is repeatable (e.g., "mem" for Memory display), * compute the ordinal number for the next occurence. If there is an instance * that is not visible, then use that one. Otherwise, it is one greater than * the last one. * @param kind the SeeCode display kind (e.g., "mem") * @return the ordinal for the next instance of this display. */ private String computeOrdinalFor(String kind) { IViewReference refs[] = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() .getViewReferences(); String prefix = kind + SeeCodeCustomView.INSTANCE_SEPARATOR; Set<String> inUse = new HashSet<String>(); for (IViewReference v : refs) { if (v.getId().equals(SeeCodeCustomView.VIEW_ID) && v.getSecondaryId().startsWith(prefix)) { String ord = v.getSecondaryId().substring(prefix.length()); if (v.getView(false) == null) { return ord; // Re use it. } else inUse.add(ord); } } for (int i = 1;; i++) { if (!inUse.contains("" + i)) { return "" + i; } } } public IViewPart createDisplay(EngineInterface engine, String kind) { try { // See if it is one of those that we have userped String viewID = sUserpedDisplayMap.get(kind); if (viewID != null) { kind = null; } else { viewID = SeeCodeCustomView.VIEW_ID; if (sRepeatableDisplays.contains(kind)) { // We have a display for which we permit multiple instances. // We want to create a new instance, regardless if there is one already // existing. kind = kind + SeeCodeCustomView.INSTANCE_SEPARATOR + computeOrdinalFor(kind); } } IViewPart view = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(viewID, kind, IWorkbenchPage.VIEW_ACTIVATE); if (view instanceof AbstractEngineBasedView) { ((AbstractEngineBasedView) view).setEngineSource(engine); } // Else SeeCode display has been aliased to a CDT display... return view; } catch (PartInitException e) { SeeCodePlugin.log(e); } return null; } /** * The font registry key that is maintained by the preference page. * It is defined as a "theme" extension. */ public static final String SEECODE_FONT = "com.arc.cdt.debug.seecode.ui.SeeCodeFont"; /** * The font registry key that is maintained by the preference page. * It is defined as a "theme" extension. */ private static final String SEECODE_FOREGROUND = "com.arc.cdt.debug.seecode.ui.SeeCodeColor"; private static final String SEECODE_BACKGROUND = "com.arc.cdt.debug.seecode.ui.color.background"; private static final String SEECODE_ERRORLOG_BACKGROUND = "com.arc.cdt.debug.seecode.ui.errorlog.background"; private static final String SEECODE_ERRORLOG_FOREGROUND = "com.arc.cdt.debug.seecode.ui.errorlog.foreground"; private static final String SEECODE_OVERLAY_BACKGROUND = "com.arc.cdt.debug.seecode.ui.color.overlay"; private static final String SEECODE_READONLY_BACKGROUND = "com.arc.cdt.debug.seecode.ui.color.readonly"; private static final String SEECODE_MISALIGNED_BACKGROUND = "com.arc.cdt.debug.seecode.ui.color.misaligned"; public static boolean isKnownColorProperty(String prop) { return SEECODE_FOREGROUND.equals(prop) || SEECODE_BACKGROUND.equals(prop) || SEECODE_OVERLAY_BACKGROUND.equals(prop) || SEECODE_READONLY_BACKGROUND.equals(prop) || SEECODE_MISALIGNED_BACKGROUND.equals(prop) || SEECODE_ERRORLOG_BACKGROUND.equals(prop) || SEECODE_ERRORLOG_FOREGROUND.equals(prop); } /** * Return the font that is to apply to each SeeCode display, and * to any editable comboboxes. Its is configurable from the Preferences * dialog. * @return the seecode display font. */ public static Font getSeeCodeFont() { return JFaceResources.getFont(SEECODE_FONT); } private static IColorPreferences COLOR_PREFERENCES = null; /** * Return preference colors for MetaWare debugger displays. * @return the seecode display color. */ public static IColorPreferences getColorPreferences() { if (COLOR_PREFERENCES == null) { COLOR_PREFERENCES = new IColorPreferences() { private IColor getColor(String prefID) { RGB rgb = JFaceResources.getColorRegistry().getRGB(prefID); return rgb != null ? getWidgetFactory().makeColor(rgb.red, rgb.green, rgb.blue) : null; } @Override public IColor getForegroundColor() { return getColor(SEECODE_FOREGROUND); } @Override public IColor getBackgroundColor() { return getColor(SEECODE_BACKGROUND); } @Override public IColor getOverlayBackgroundColor() { return getColor(SEECODE_OVERLAY_BACKGROUND); } @Override public IColor getReadonlyBackgroundColor() { return getColor(SEECODE_READONLY_BACKGROUND); } @Override public IColor getMisalignedBackgroundColor() { return getColor(SEECODE_MISALIGNED_BACKGROUND); } @Override public IColor getErrorLogBackgroundColor() { return getColor(SEECODE_ERRORLOG_BACKGROUND); } @Override public IColor getErrorLogForegroundColor() { return getColor(SEECODE_ERRORLOG_FOREGROUND); } }; } return COLOR_PREFERENCES; } /** * {@inheritDoc} Implementation of overridden (or abstract) method. * @param context * @throws Exception */ @Override public void start(BundleContext context) throws Exception { super.start(context); fAnimateToolBarMgr = new AnimateToolBarManager(); IAdapterManager manager = Platform.getAdapterManager(); SeeCodeAdapterFactory f = new SeeCodeAdapterFactory(); manager.registerAdapters(f, ILaunch.class); } public AnimateToolBarManager getAnimateToolBarManager() { return fAnimateToolBarMgr; } @Override public void stop(BundleContext context) throws Exception { // If SeeCode core plugin hasn't yet stopped, then // close all active sessions. Otherwise, the engine may // be sending updates to dead plugins while Eclipse is // shutting down. This causes all sorts of errors to // appear in the error log. if (!SeeCodePlugin.getDefault().isStopped()) { SeeCodePlugin.getDefault().shutdownSessions(); } super.stop(context); } /** * The default seecode options for any new configurations. */ private static QualifiedName GENERIC = computeSeeCodeOptionName("*"); /** * The old MetaDeveloper importer will have retrieved SeeCode options that need * to be stored someplace, so that they can be used as initial values when * a new Launch configuration is built. * <P> * We base them on the project and a configuration ID, since mult-project project * spaces can be imported into the same project in different configurations. * @param project the project * @param configID the configuration ID * @param options the initial seecode options for any launch configuration based on * this project. */ public void setDefaultSeeCodeOptions(IProject project, String configID, Map<String, String> options) { QualifiedName name = computeSeeCodeOptionName(configID); StringBuilder encoding = new StringBuilder(100); //Sort the keys so that we can compare below to storing identical maps for // each configuration. List<String> sortedKeys = new ArrayList<String>(options.keySet()); Collections.sort(sortedKeys); for (String key : sortedKeys) { encoding.append(key); encoding.append('='); encoding.append(options.get(key)); encoding.append('\n'); } // Avoid storing options for each configuration if they are all identical. try { String encoded = encoding.toString(); String prev = project.getPersistentProperty(GENERIC); if (prev == null) { project.setPersistentProperty(GENERIC, encoded); } else if (!prev.equals(encoded)) project.setPersistentProperty(name, encoded); } catch (CoreException e) { SeeCodePlugin.log(e); } } /** * @param configID the configuration ID. * @return seecode option name for the persistent storage, given a configuration ID. */ private static QualifiedName computeSeeCodeOptionName(String configID) { return new QualifiedName("SeeCodeOptions", configID); } /** * Retrieve any initial seecode options that may have been imported from * an old MetaDeveloper project. * @return any initial seecode options imported from old MetaDeveloper, or <code>null</code>. */ public Map<String, String> getDefaultSeeCodeOptions(IProject project, String configID) { try { String encoding = project.getPersistentProperty(computeSeeCodeOptionName(configID)); if (encoding == null) { encoding = project.getPersistentProperty(GENERIC); if (encoding == null) return null; } HashMap<String, String> map = new HashMap<String, String>(); String keyValue[] = encoding.split("\\n"); for (String kv : keyValue) { int index = kv.indexOf('='); String key = kv.substring(0, index); String value = kv.substring(index + 1); map.put(key, value); } return map; } catch (CoreException e) { SeeCodePlugin.log(e); return null; } catch (RuntimeException e) { SeeCodePlugin.log(e); return null; } } /** * Returns the image descriptor with the given relative path. */ public ImageDescriptor getImageDescriptor(String relativePath) { URL url = FileLocator.find(getBundle(), new Path(relativePath), null); return url != null ? ImageDescriptor.createFromURL(url) : null; } public Image getImage(String relativePath) { ImageRegistry registry = getImageRegistry(); Image image = registry.get(relativePath); if (image == null) { ImageDescriptor desc = getImageDescriptor(relativePath); if (desc != null) { registry.put(relativePath, desc); image = registry.get(relativePath); } } return image; } public Image getDebuggerIcon() { return getImage("icons/small_meta.gif"); } public static IStatus makeErrorStatus(String msg) { return new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, msg, null); } public static IStatus makeErrorStatus(String msg, Throwable t) { return new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, msg, t); } /** * Show an error box. * (We use JFace ErrorDialog instead of MessageBox. The latter is done outside * of Java and the WindowTester framework loses control). * @param title * @param message */ public static void showError(String title, String message) { Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); ErrorDialog.openError(shell, title, null, makeErrorStatus(message)); } private static final int NOTE_TIME_OUT = 12000; /** * Show an note box. * (We use JFace ErrorDialog instead of MessageBox. The latter is done outside * of Java and the WindowTester framework loses control). * @param title * @param message */ public static void showNote(String title, String message) { Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); MessageDialog dialog = new MessageDialog(shell, title, null, // accept // the // default // window // icon message, MessageDialog.INFORMATION, new String[] { IDialogConstants.OK_LABEL }, 0); dialog.setBlockOnOpen(false); // we want to be able to make box expire // ok is the default dialog.open(); long expireTime = System.currentTimeMillis() + NOTE_TIME_OUT; Display display = shell.getDisplay(); try { while (dialog.getShell() != null && !dialog.getShell().isDisposed() && System.currentTimeMillis() < expireTime) { if (!display.readAndDispatch()) { display.sleep(); } } } finally { if (dialog.getShell() != null && !dialog.getShell().isDisposed()) { dialog.close(); } } } /** * Show an error box. * (We use JFace ErrorDialog instead of MessageBox. The latter is done outside * of Java and the WindowTester framework loses control). * @param title * @param msg */ public static void showError(String title, String msg, Throwable e) { Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); ErrorDialog.openError(shell, title, null, makeErrorStatus(msg, e)); } public static void log(IStatus status) { getDefault().getLog().log(status); } public static void log(String msg, Throwable e) { log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, msg, e)); } public static void log(String msg) { log(makeErrorStatus(msg)); } public static void log(Throwable e) { log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.ERROR, "Error", e)); //$NON-NLS-1$ } }