fr.opensagres.eclipse.jsbuild.internal.ui.views.actions.BuildFileOpenWithMenu.java Source code

Java tutorial

Introduction

Here is the source code for fr.opensagres.eclipse.jsbuild.internal.ui.views.actions.BuildFileOpenWithMenu.java

Source

/**
 *  Copyright (c) 2013-2014 Angelo ZERR.
 *  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:
 *  Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation
 */
package fr.opensagres.eclipse.jsbuild.internal.ui.views.actions;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;

import fr.opensagres.eclipse.jsbuild.core.IJSBuildFileNode;
import fr.opensagres.eclipse.jsbuild.internal.ui.EditorUtility;
import fr.opensagres.eclipse.jsbuild.internal.ui.JSBuildFileUIPlugin;
import fr.opensagres.eclipse.jsbuild.internal.ui.Logger;

/**
 * 
 * Code mostly a copy of the OpenWithMenu which cannot be effectively
 * sub-classed
 */
public class BuildFileOpenWithMenu extends ContributionItem {

    private IWorkbenchPage fPage;
    private IEditorRegistry fRegistry = PlatformUI.getWorkbench().getEditorRegistry();
    private static final String SYSTEM_EDITOR_ID = PlatformUI.PLUGIN_ID + ".SystemEditor"; //$NON-NLS-1$

    private static Map<ImageDescriptor, Image> imageCache = new Hashtable<ImageDescriptor, Image>(11);

    private IJSBuildFileNode fNode;

    /**
     * The id of this action.
     */
    public static final String ID = JSBuildFileUIPlugin.PLUGIN_ID + ".JSBuildFileOpenWithMenu"; //$NON-NLS-1$

    public BuildFileOpenWithMenu(IWorkbenchPage page) {
        super(ID);
        this.fPage = page;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.action.IContributionItem#dispose()
     */
    @Override
    public void dispose() {
        super.dispose();
        for (Image image : imageCache.values()) {
            image.dispose();
        }
        imageCache.clear();
    }

    /**
     * Returns an image to show for the corresponding editor descriptor.
     * 
     * @param editorDesc
     *            the editor descriptor, or <code>null</code> for the system
     *            editor
     * @return the image or <code>null</code>
     */
    private Image getImage(IEditorDescriptor editorDesc) {
        ImageDescriptor imageDesc = getImageDescriptor(editorDesc);
        if (imageDesc == null) {
            return null;
        }
        Image image = imageCache.get(imageDesc);
        if (image == null) {
            image = imageDesc.createImage();
            imageCache.put(imageDesc, image);
        }
        return image;
    }

    /**
     * Returns the image descriptor for the given editor descriptor, or
     * <code>null</code> if it has no image.
     */
    private ImageDescriptor getImageDescriptor(IEditorDescriptor editorDesc) {
        ImageDescriptor imageDesc = null;
        if (editorDesc == null) {
            imageDesc = fRegistry.getImageDescriptor(fNode.getBuildFile().getBuildFileResource().getName());
        } else {
            imageDesc = editorDesc.getImageDescriptor();
        }
        if (imageDesc == null && editorDesc != null) {
            if (editorDesc.getId().equals(SYSTEM_EDITOR_ID)) {
                imageDesc = getSystemEditorImageDescriptor(
                        fNode.getBuildFile().getBuildFileResource().getFileExtension());
            }
        }
        return imageDesc;
    }

    /**
     * Return the image descriptor of the system editor that is registered with
     * the OS to edit files of this type. <code>null</code> if none can be
     * found.
     */
    private ImageDescriptor getSystemEditorImageDescriptor(String extension) {
        Program externalProgram = null;
        if (extension != null) {
            externalProgram = Program.findProgram(extension);
        }
        if (externalProgram == null) {
            return null;
        }
        return new EditorImageDescriptor(externalProgram);
    }

    /**
     * Creates the menu item for the editor descriptor.
     * 
     * @param menu
     *            the menu to add the item to
     * @param descriptor
     *            the editor descriptor, or null for the system editor
     * @param preferredEditor
     *            the descriptor of the preferred editor, or <code>null</code>
     */
    private void createMenuItem(Menu menu, final IEditorDescriptor descriptor,
            final IEditorDescriptor preferredEditor) {
        // XXX: Would be better to use bold here, but SWT does not support it.
        final MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
        boolean isPreferred = preferredEditor != null && descriptor.getId().equals(preferredEditor.getId());
        menuItem.setSelection(isPreferred);
        menuItem.setText(descriptor.getLabel());
        Image image = getImage(descriptor);
        if (image != null) {
            menuItem.setImage(image);
        }
        Listener listener = new Listener() {
            /*
             * (non-Javadoc)
             * 
             * @see
             * org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.
             * widgets.Event)
             */
            @Override
            public void handleEvent(Event event) {
                switch (event.type) {
                case SWT.Selection:
                    if (menuItem.getSelection()) {
                        openEditor(descriptor);
                    }
                    break;
                default:
                    break;
                }
            }
        };
        menuItem.addListener(SWT.Selection, listener);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.jface.action.IContributionItem#fill(org.eclipse.swt.widgets
     * .Menu, int)
     */
    @Override
    public void fill(Menu menu, int index) {
        IFile fileResource = fNode.getBuildFile().getBuildFileResource();
        if (fileResource == null) {
            return;
        }

        IEditorDescriptor defaultEditor = fRegistry.findEditor(IEditorRegistry.SYSTEM_INPLACE_EDITOR_ID); // should
        // not
        // be
        // null
        IEditorDescriptor preferredEditor = IDE.getDefaultEditor(fileResource); // may
        // be
        // null

        IEditorDescriptor[] editors = fRegistry.getEditors(fileResource.getName());
        Arrays.sort(editors, new Comparator<IEditorDescriptor>() {
            /*
             * (non-Javadoc)
             * 
             * @see java.util.Comparator#compare(java.lang.Object,
             * java.lang.Object)
             */
            @Override
            public int compare(IEditorDescriptor o1, IEditorDescriptor o2) {
                String s1 = o1.getLabel();
                String s2 = o2.getLabel();
                // Return true if elementTwo is 'greater than' elementOne
                return s1.compareToIgnoreCase(s2);
            }
        });
        IEditorDescriptor javaScriptEditor = fRegistry.findEditor("org.eclipse.wst.jsdt.ui.CompilationUnitEditor"); //$NON-NLS-1$

        boolean defaultFound = false;
        boolean antFound = false;
        List<String> alreadyAddedEditors = new ArrayList<String>(editors.length);
        for (int i = 0; i < editors.length; i++) {
            IEditorDescriptor editor = editors[i];
            if (alreadyAddedEditors.contains(editor.getId())) {
                continue;
            }
            createMenuItem(menu, editor, preferredEditor);
            if (defaultEditor != null && editor.getId().equals(defaultEditor.getId())) {
                defaultFound = true;
            }
            if (javaScriptEditor != null && editor.getId().equals(javaScriptEditor.getId())) {
                antFound = true;
            }
            alreadyAddedEditors.add(editor.getId());

        }

        // Only add a separator if there is something to separate
        if (editors.length > 0) {
            new MenuItem(menu, SWT.SEPARATOR);
        }

        // Add ant editor.
        if (!antFound && javaScriptEditor != null) {
            createMenuItem(menu, javaScriptEditor, preferredEditor);
        }

        // Add default editor.
        if (!defaultFound && defaultEditor != null) {
            createMenuItem(menu, defaultEditor, preferredEditor);
        }

        // Add system editor.
        IEditorDescriptor descriptor = fRegistry.findEditor(IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID);
        createMenuItem(menu, descriptor, preferredEditor);
        createDefaultMenuItem(menu, fileResource);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.action.IContributionItem#isDynamic()
     */
    @Override
    public boolean isDynamic() {
        return true;
    }

    /**
     * Opens the given editor on the selected file.
     * 
     * @param editor
     *            the editor descriptor, or <code>null</code> for the system
     *            editor
     */
    private void openEditor(IEditorDescriptor editorDescriptor) {
        EditorUtility.openInEditor(fPage, editorDescriptor, fNode);
    }

    /**
     * Creates the menu item for the default editor
     * 
     * @param menu
     *            the menu to add the item to
     * @param file
     *            the file being edited
     * @param registry
     *            the editor registry
     */
    private void createDefaultMenuItem(Menu menu, final IFile fileResource) {
        final MenuItem menuItem = new MenuItem(menu, SWT.RADIO);
        menuItem.setSelection(IDE.getDefaultEditor(fileResource) == null);
        menuItem.setText(JSBuildFileViewActionMessages.JSBuildFileViewOpenWithMenu_Default_Editor_4);

        Listener listener = new Listener() {
            /*
             * (non-Javadoc)
             * 
             * @see
             * org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.
             * widgets.Event)
             */
            @Override
            public void handleEvent(Event event) {
                switch (event.type) {
                case SWT.Selection:
                    if (menuItem.getSelection()) {
                        IDE.setDefaultEditor(fileResource, null);
                        try {
                            IDE.openEditor(fPage, fileResource, true);
                        } catch (PartInitException e) {
                            Logger.logException(MessageFormat.format(
                                    JSBuildFileViewActionMessages.JSBuildFileViewOpenWithMenu_Editor_failed,
                                    new Object[] { fileResource.getLocation().toOSString() }), e);
                        }
                    }
                    break;
                default:
                    break;
                }
            }
        };

        menuItem.addListener(SWT.Selection, listener);
    }

    public void setNode(IJSBuildFileNode node) {
        fNode = node;
    }
}