org.eclipse.edt.ide.ui.internal.handlers.FormattingHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.edt.ide.ui.internal.handlers.FormattingHandler.java

Source

/*******************************************************************************
 * Copyright  2000, 2013 IBM Corporation and others.
 * 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:
 * IBM Corporation - initial API and implementation
 *
 *******************************************************************************/
package org.eclipse.edt.ide.ui.internal.handlers;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.edt.ide.core.model.EGLCore;
import org.eclipse.edt.ide.core.model.IBuffer;
import org.eclipse.edt.ide.core.model.IEGLElement;
import org.eclipse.edt.ide.core.model.IEGLFile;
import org.eclipse.edt.ide.core.model.IRegion;
import org.eclipse.edt.ide.ui.EDTUIPlugin;
import org.eclipse.edt.ide.ui.internal.CodeFormatterUtil;
import org.eclipse.edt.ide.ui.internal.EGLUI;
import org.eclipse.edt.ide.ui.internal.UINlsStrings;
import org.eclipse.edt.ide.ui.internal.actions.WorkbenchRunnableAdapter;
import org.eclipse.edt.ide.ui.internal.codemanipulation.OrganizeImportsOperation.SyntaxErrorHelper;
import org.eclipse.edt.ide.ui.internal.dialogs.OptionalMessageDialog;
import org.eclipse.edt.ide.ui.internal.dialogs.ProblemDialog;
import org.eclipse.edt.ide.ui.internal.editor.DocumentAdapter;
import org.eclipse.edt.ide.ui.internal.editor.EGLEditor;
import org.eclipse.edt.ide.ui.internal.formatting.FormattingStrategy;
import org.eclipse.edt.ide.ui.internal.formatting.ui.ProfileManager;
import org.eclipse.edt.ide.ui.internal.util.EditorUtility;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.text.DocumentRewriteSession;
import org.eclipse.jface.text.DocumentRewriteSessionType;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IDocumentExtension4;
import org.eclipse.jface.text.formatter.FormattingContext;
import org.eclipse.jface.text.formatter.FormattingContextProperties;
import org.eclipse.jface.text.formatter.IFormattingContext;
import org.eclipse.jface.text.formatter.MultiPassContentFormatter;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.eclipse.ui.progress.IProgressService;
import org.eclipse.ui.texteditor.ITextEditor;

public class FormattingHandler extends EGLHandler {

    private DocumentRewriteSession fRewriteSession;
    private IRegion fPartialRegion = null;

    @Override
    public Object execute(ExecutionEvent event) throws ExecutionException {

        // Initialize editor if called from EGL Editor
        if (isInvokedFromEditorContext(event)) {
            IEditorPart editor = getCurrentActiveEditor(event);
            if (editor instanceof EGLEditor) {
                fEditor = (EGLEditor) editor;
                if (editor != null) {
                    IEditorInput editorInput = editor.getEditorInput();
                    // Could be a VirtualEditorInput if coming from PageDesigners QEV
                    if (editorInput instanceof IFileEditorInput) {
                        IResource resource = ((IFileEditorInput) editorInput).getFile();
                        IEGLElement element = EGLCore.create(resource);
                        fSite = editor.getSite();
                        fSelection = new StructuredSelection(element);
                    }
                }
            }
        }

        if (fSelection != null) {
            run();
        }
        return null;
    }

    public void run() {
        List eglFiles = getEGLFiles(fSelection);
        int selCnt = eglFiles.size();
        if (selCnt == 0)
            return;

        if (selCnt > 1 && fSite != null) {
            int returnCode = OptionalMessageDialog.open("EGLFormat", //$NON-NLS-1$
                    fSite.getShell(), UINlsStrings.FormatTitle, null, UINlsStrings.UndoNotSupportedMsg,
                    MessageDialog.WARNING,
                    new String[] { IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL }, 0);
            if (returnCode != OptionalMessageDialog.NOT_SHOWN && returnCode != Window.OK) {
                return;
            }
        }
        if (selCnt > 1) {
            runOnMultiple(eglFiles, null);
        } else {
            runOnSingle((IEGLFile) eglFiles.get(0));
        }
    }

    private void runOnMultiple(final List eglfiles, final String formatProfileName) {
        String message = UINlsStrings.FormatComplete;
        final MultiStatus status = new MultiStatus(EDTUIPlugin.PLUGIN_ID, IStatus.OK, message, null);

        IProgressService progressService = PlatformUI.getWorkbench().getProgressService();

        try {
            if (eglfiles.size() == 1) {
                Object eglFile = eglfiles.get(0);
                EditorUtility.openInEditor(eglFile);
                fileNeedsSave.put(eglFile, EditorUtility.isOpenInEditor(eglFile));
            }

            progressService.run(true, true, new WorkbenchRunnableAdapter(new IWorkspaceRunnable() {
                public void run(IProgressMonitor monitor) throws CoreException {
                    doRunOnMultiple(eglfiles, formatProfileName, status, monitor);
                }
            }));

            if (!status.isOK() && fSite != null) {
                String title = UINlsStrings.EGLFormatting;
                ProblemDialog.open(fSite.getShell(), title, null, status);
            }
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            //cancel by user
        } catch (CoreException ex) {
            ex.printStackTrace();
        }
    }

    private void doRunOnMultiple(List eglfiles, String formatProfileName, MultiStatus status,
            IProgressMonitor monitor) throws OperationCanceledException {
        if (monitor == null) {
            monitor = new NullProgressMonitor();
        }
        monitor.setTaskName(UINlsStrings.FormattingProgress);

        int size = eglfiles.size();
        monitor.beginTask("", size * 4); //$NON-NLS-1$

        try {
            for (int i = 0; i < size; i++) {
                if (monitor.isCanceled()) {
                    throw new OperationCanceledException();
                }
                IEGLFile eglfile = (IEGLFile) (eglfiles.get(i));
                try {
                    SyntaxErrorHelper synErr = runFormat(eglfile, formatProfileName, monitor);
                    if (synErr != null) {
                        String msg = UINlsStrings.bind(UINlsStrings.SyntaxError,
                                new String[] { eglfile.getPath().makeRelative().toString() });
                        status.add(new Status(IStatus.INFO, EDTUIPlugin.PLUGIN_ID, IStatus.ERROR, msg, null));
                    }
                } catch (CoreException e) {
                    status.add(e.getStatus());
                }
            }
        } finally {
            monitor.done();
        }
    }

    private SyntaxErrorHelper runFormat(IEGLFile eglfile, String formatProfileName, IProgressMonitor monitor)
            throws CoreException {
        IPath path = eglfile.getPath();

        SyntaxErrorHelper synErr = null;
        ITextFileBufferManager manager = FileBuffers.getTextFileBufferManager();
        boolean connectedTextBuffer = false;
        IEGLFile workingCopy = null;
        try {
            Object editorpart = fileNeedsSave.get(eglfile);
            boolean needSave = editorpart == null;

            IDocument doc = null;
            if (!needSave) {//means the file is opened in an editor                     
                if (editorpart instanceof EGLEditor || editorpart instanceof MultiPageEditorPart) {
                    synchronized (eglfile) {
                        workingCopy = (IEGLFile) (eglfile.getSharedWorkingCopy(null, EGLUI.getBufferFactory(),
                                null));
                    }
                    IBuffer buf = workingCopy.getBuffer();
                    if (buf instanceof DocumentAdapter) {
                        doc = ((DocumentAdapter) buf).getDocument();
                    }
                }
            }

            ITextFileBuffer filebuffer = null;
            if (doc == null) {
                manager.connect(path, new SubProgressMonitor(monitor, 1));
                connectedTextBuffer = true;
                filebuffer = manager.getTextFileBuffer(path);
                doc = filebuffer.getDocument();
            }
            String filePathLocation = path.makeRelative().toString();
            monitor.subTask(filePathLocation);
            synErr = formatEGLFile(doc, formatProfileName, needSave);
            //synErr = doFormat(doc, formatProfileName);

            if (needSave && filebuffer != null && filebuffer.isDirty()) {
                filebuffer.commit(new SubProgressMonitor(monitor, 2), false);
            } else
                monitor.worked(2);
        } finally {
            if (workingCopy != null)
                workingCopy.destroy();

            if (connectedTextBuffer)
                manager.disconnect(path, new SubProgressMonitor(monitor, 1));
        }
        return synErr;
    }

    private SyntaxErrorHelper formatEGLFile(final IDocument document, final String formatProfileName,
            final boolean needSave) {
        final SyntaxErrorHelper[] synErr = new SyntaxErrorHelper[1];
        if (!needSave && fSite != null) {
            fSite.getShell().getDisplay().syncExec(new Runnable() {
                public void run() {
                    synErr[0] = doFormat(document, formatProfileName);
                }
            });
        } else {
            synErr[0] = doFormat(document, formatProfileName); //run in context thread
        }
        return synErr[0];
    }

    private SyntaxErrorHelper doFormat(IDocument document, String formatProfileName) {
        ProfileManager profileMgr = ProfileManager.getInstance();
        //save the original selected profile
        EObject originalSelProfile = profileMgr.getSelectedProfile();

        Map options = CodeFormatterUtil.getFormattingOptionMapByProfileName(formatProfileName, profileMgr);
        final IFormattingContext context = new FormattingContext();
        FormattingStrategy eglFormattingStrategy = new FormattingStrategy();
        try {
            context.setProperty(FormattingContextProperties.CONTEXT_PREFERENCES, options);

            if (fPartialRegion != null) {
                context.setProperty(FormattingContextProperties.CONTEXT_REGION, fPartialRegion);
                context.setProperty(FormattingContextProperties.CONTEXT_DOCUMENT, Boolean.FALSE);
            } else
                context.setProperty(FormattingContextProperties.CONTEXT_DOCUMENT, Boolean.TRUE);
            final MultiPassContentFormatter formatter = new MultiPassContentFormatter(
                    IDocumentExtension3.DEFAULT_PARTITIONING, IDocument.DEFAULT_CONTENT_TYPE);
            formatter.setMasterStrategy(eglFormattingStrategy);
            ;

            try {
                startSequentialRewriteMode(document);
                formatter.format(document, context);
            } finally {
                stopSequentialRewriteMode(document);
            }
        } finally {
            context.dispose();
            //reset the current format profile selection back to its original
            profileMgr.setSelectedProfile(originalSelProfile);
        }

        SyntaxErrorHelper synErr = eglFormattingStrategy.get1stSyntaxErrorMsg();
        return synErr;
    }

    private void startSequentialRewriteMode(IDocument document) {
        if (document instanceof IDocumentExtension4) {
            IDocumentExtension4 extension = (IDocumentExtension4) document;
            fRewriteSession = extension.startRewriteSession(DocumentRewriteSessionType.SEQUENTIAL);
        } else if (document instanceof IDocumentExtension) {
            IDocumentExtension extension = (IDocumentExtension) document;
            extension.startSequentialRewrite(false);
        }
    }

    private void stopSequentialRewriteMode(IDocument document) {
        if (document instanceof IDocumentExtension4) {
            IDocumentExtension4 extension = (IDocumentExtension4) document;
            extension.stopRewriteSession(fRewriteSession);
        } else if (document instanceof IDocumentExtension) {
            IDocumentExtension extension = (IDocumentExtension) document;
            extension.stopSequentialRewrite();
        }
    }

    private void runOnSingle(final IEGLFile eglFile) {
        try {
            IEditorPart editor = EditorUtility.openInEditor(eglFile);
            fileNeedsSave.put(eglFile, EditorUtility.isOpenInEditor(eglFile));

            IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
            IRunnableContext context = fSite != null ? fSite.getWorkbenchWindow() : null;
            if (context == null) {
                context = progressService;
            }

            final SyntaxErrorHelper[] synErr = new SyntaxErrorHelper[1];
            progressService.run(true, true, new WorkbenchRunnableAdapter(new IWorkspaceRunnable() {
                public void run(final IProgressMonitor monitor) throws CoreException {
                    synErr[0] = runFormat(eglFile, null, monitor);
                }
            }));

            postRun(synErr[0], (editor instanceof ITextEditor) ? (ITextEditor) editor : null);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
        } catch (CoreException ex) {
            ex.printStackTrace();
        }
    }

    protected void postRun(SyntaxErrorHelper syntaxErr, ITextEditor editor) {
        if (syntaxErr != null) {
            MessageDialog.openInformation(fSite.getShell(), UINlsStrings.EGLFormatting, syntaxErr.fErrMsg);

            //highlight the syntax error location
            if (editor != null && syntaxErr.fSynErr.startOffset > 0)
                editor.selectAndReveal(syntaxErr.fSynErr.startOffset,
                        syntaxErr.fSynErr.endOffset - syntaxErr.fSynErr.startOffset + 1);
        }
    }

}