/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.ui.common; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; import org.eclipse.swt.SWTException; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWindowListener; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.forms.FormColors; import org.eclipse.ui.forms.widgets.FormToolkit; import org.osgi.framework.BundleContext; import org.osgi.service.prefs.BackingStoreException; import org.teiid.core.designer.PluginUtil; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.ui.common.actions.ActionService; import org.teiid.designer.ui.common.graphics.ImageImageDescriptor; import org.teiid.designer.ui.common.product.IProductContext; import org.teiid.designer.ui.common.product.ProductCustomizerMgr; /** * The main plugin class to be used in the desktop. * * @since 8.0 */ public abstract class AbstractUiPlugin extends org.eclipse.ui.plugin.AbstractUIPlugin { /** List of all opened windows in this application */ static List<IWorkbenchWindow> windowList = new ArrayList<IWorkbenchWindow>(3); /** Map of action services keyed by the workbench window. */ Map<IWorkbenchWindow, ActionService> windowServiceMap; /** Cache off the last active workbench window */ IWorkbenchWindow lastActiveWorkbenchWindow; private FormColors formColors; private FormToolkit ftk; private static IWorkbenchPage lastPage; private void constructAbstractUiPlugin() { windowServiceMap = new HashMap<IWorkbenchWindow, ActionService>(); // Each window will have their own action service since each window has there own selection service. // The services are created in the getActionService(IWorkbenchWindow) method and removed in the // following listener. IWorkbench workbench = getWorkbench(); if (workbench == null) { return; } // add a perspective listener to synchronize the last active editor with each perspective IWorkbenchWindow theWindow = workbench.getActiveWorkbenchWindow(); if (theWindow != null && !windowList.contains(theWindow)) { theWindow.addPerspectiveListener(new EditorPerspectiveListener(theWindow)); windowList.add(theWindow); } workbench.addWindowListener(new IWindowListener() { @Override public void windowActivated( IWorkbenchWindow theWindow ) { lastActiveWorkbenchWindow = theWindow; } @Override public void windowDeactivated( IWorkbenchWindow theWindow ) { } @Override public void windowClosed( IWorkbenchWindow theWindow ) { // remove the service from the map since the window closed windowServiceMap.remove(theWindow); windowList.remove(theWindow); } @Override public void windowOpened( IWorkbenchWindow theWindow ) { if (!windowList.contains(theWindow)) { // add a listener to synchronize the active editor with the perspective theWindow.addPerspectiveListener(new EditorPerspectiveListener(theWindow)); windowList.add(theWindow); } } }); } // ============================================================================================================================ // Abstract Methods /** * Creates an <code>ActionService</code> for the given window. * * @param theWindow the window whose <code>ActionService</code> is being requested * @return the newly created service */ protected abstract ActionService createActionService( IWorkbenchPage page ); /** * @since 4.0 */ public abstract PluginUtil getPluginUtil(); // ============================================================================================================================ // Declared Methods /** * @since 4.0 */ private ImageDescriptor createImageDescriptor( final String key ) { try { final URL url = new URL(getBundle().getEntry("/").toString() + key); //$NON-NLS-1$ final ImageDescriptor descriptor = ImageDescriptor.createFromURL(url); final ImageRegistry registry = getImageRegistry(); registry.put(key, descriptor); return descriptor; } catch (final MalformedURLException err) { getPluginUtil().log(err); return null; } } /** * Gets the <code>ActionService</code> associated with the given <code>IWorkbenchWindow</code>. If a service does not exist, * one is created. * * @param theWindow the window whose <code>ActionService</code> is being requested * @return the action service */ public ActionService getActionService( IWorkbenchPage pg ) { if (this.windowServiceMap == null) { constructAbstractUiPlugin(); } if (pg != null) { // save off any valid pages that come through lastPage = pg; } else { // try to recover a valid page so we can continue: pg = lastPage; } // endif if( pg != null ) { IWorkbenchWindow theWindow = pg.getWorkbenchWindow(); ActionService service = windowServiceMap.get(theWindow); if (service == null) { service = createActionService(pg); windowServiceMap.put(theWindow, service); } return service; } return null; } /** * Retrieves the image associated with the specified key from the {@link org.eclipse.jface.resource.ImageRegistry image * registry}, creating the image and registering it if it doesn't already exist. A null key will cause the descriptor for the * "No image" image to be returned. * * @param key The key associated with the image to retrieve. This must be in the form of the path to the image file relative * to this plug-in's folder; may be null. * @return The image associated with the specified key. * @since 4.0 */ public final Image getImage( final String key ) { final ImageRegistry registry = getImageRegistry(); Image img = registry.get(key); if (img != null) { return img; } try { createImageDescriptor(key); img = registry.get(key); return img != null ? img : ImageDescriptor.getMissingImageDescriptor().createImage(); } catch (final SWTException err) { getPluginUtil().log(IStatus.WARNING, err, err.getMessage()); return null; } } /** * Retrieves the image descriptor associated with the specified key from the {@link org.eclipse.jface.resource.ImageRegistry * image registry}, creating the descriptor and registering it if it doesn't already exist. A null key will cause the * descriptor for the "No image" image to be returned. * * @param key The key associated with the image descriptor to retrieve. This must be in the form of the path to the image file * relative to this plug-in's folder; may be null. * @return The image descriptor associated with the specified key. * @since 4.0 */ public final ImageDescriptor getImageDescriptor( final String key ) { final ImageRegistry registry = getImageRegistry(); final ImageDescriptor descriptor = registry.getDescriptor(key); if (descriptor != null) { return descriptor; } return createImageDescriptor(key); } /** * Convenience method to obtain the last active IWorkbenchWindow. Since Workbench.getActiveWorkbenchWindow frequently returns * null, this method will return the last WorkbenchWindow that was activated. The method will always try to obtain the active * IWorkbenchWindow from the Workbench, but if it is null the method will return the cached value. * * @return the last active WorkbenchWindow, if one was ever activated. */ public final IWorkbenchWindow getCurrentWorkbenchWindow() { IWorkbenchWindow result = getWorkbench().getActiveWorkbenchWindow(); if (result == null) { result = lastActiveWorkbenchWindow; } return result; } /** * Obtains the current values of all plugin preferences. * <p> * <strong>This method should be used instead of <code>getPluginPreferences()</code>.</strong> * * @return the preferences (never <code>null</code>) */ public final IEclipsePreferences getPreferences() { return ModelerCore.getPreferences(getBundle().getSymbolicName()); } /** * Persists plugin preferences. */ public final void savePreferences() { try { ModelerCore.savePreferences(getBundle().getSymbolicName()); } catch (BackingStoreException e) { getPluginUtil().log(e); } } /** * Obtains the default values of all plugin preferences. * <p> * <strong>This method should be used instead of <code>getPluginPreferences()</code>.</strong> * * @return the preferences (never <code>null</code>) */ public final IEclipsePreferences getDefaultPreferences() { return ModelerCore.getDefaultPreferences(getBundle().getSymbolicName()); } /** * Indicates if the image registry contains an image accessed by the specified identifier. * * @param imageId the identifier of the image * @return <code>true</code> if exists; <code>false</code> otherwise. */ public boolean isImageRegistered( final String imageId ) { return (getImageRegistry().get(imageId) != null); } /** * @since 4.0 */ protected void registerPluginImage( final String plugin, final String key ) { final ImageRegistry registry = getImageRegistry(); final URL viewsUrl = Platform.getBundle(plugin).getEntry("/"); //$NON-NLS-1$ try { final URL url = new URL(viewsUrl + key); final ImageDescriptor descriptor = ImageDescriptor.createFromURL(url); if( registry.get(key) != null ) { registry.put(key, descriptor); } } catch (final MalformedURLException err) { getPluginUtil().log(err); } } /** * Puts the specified <code>Image</code> in this plugin's image registry with the specified identifier. * * @param key the identifier of the image in the registry * @param image the image being put in the image registry */ public void registerPluginImage( final String key, final Image image ) { final ImageRegistry registry = getImageRegistry(); registry.put(key, new ImageImageDescriptor(image)); } /** * <p> * {@inheritDoc} * </p> * * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) */ @Override public void stop( BundleContext context ) throws Exception { // shutdown action services before shutdown if (this.windowServiceMap != null) { Iterator<ActionService> itr = windowServiceMap.values().iterator(); while (itr.hasNext()) { ActionService actionService = itr.next(); actionService.shutdown(); } } super.stop(context); } public FormToolkit getFormToolkit( Display display ) { if (ftk == null) { ftk = new FormToolkit(getFormColors(display)); } // endif return ftk; } private FormColors getFormColors( Display display ) { if (formColors == null) { formColors = new FormColors(display); formColors.markShared(); } return formColors; } /** * Indicates if the specified {@link IProductContext} is supported. * * @param theContext the context whose support status is being requested * @return <code>true</code> if supported; <code>false</code> otherwise. * @since 4.3 */ public boolean isProductContextSupported( IProductContext theContext ) { return ProductCustomizerMgr.getInstance().supports(theContext); } /** * Indicates if the specified value is supported by the given {@link IProductContext}. * * @param theContext the context containing the value * @param theValue the value whose support status is being requested * @return <code>true</code> if supported; <code>false</code> otherwise. * @since 4.3 */ public boolean isProductContextValueSupported( IProductContext theContext, Object theValue ) { return ProductCustomizerMgr.getInstance().supports(theContext, theValue); } public static IWorkbenchPage getLastValidPage() { return lastPage; } }