com.google.dart.tools.ui.callhierarchy.CallHierarchyUI.java Source code

Java tutorial

Introduction

Here is the source code for com.google.dart.tools.ui.callhierarchy.CallHierarchyUI.java

Source

/*
 * Copyright (c) 2012, the Dart project authors.
 * 
 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.dart.tools.ui.callhierarchy;

import com.google.dart.tools.core.model.DartElement;
import com.google.dart.tools.core.model.DartModelException;
import com.google.dart.tools.core.model.SourceRange;
import com.google.dart.tools.core.model.SourceReference;
import com.google.dart.tools.core.model.TypeMember;
import com.google.dart.tools.ui.DartToolsPlugin;
import com.google.dart.tools.ui.DartUI;
import com.google.dart.tools.ui.Messages;
import com.google.dart.tools.ui.internal.actions.SelectionConverter;
import com.google.dart.tools.ui.internal.callhierarchy.CallHierarchy;
import com.google.dart.tools.ui.internal.callhierarchy.CallLocation;
import com.google.dart.tools.ui.internal.callhierarchy.MethodWrapper;
import com.google.dart.tools.ui.internal.text.DartStatusConstants;
import com.google.dart.tools.ui.internal.text.editor.EditorUtility;
import com.google.dart.tools.ui.internal.util.ExceptionHandler;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.texteditor.ITextEditor;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class CallHierarchyUI {
    private static final int DEFAULT_MAX_CALL_DEPTH = 10;
    private static final String PREF_MAX_CALL_DEPTH = "PREF_MAX_CALL_DEPTH"; //$NON-NLS-1$

    private static CallHierarchyUI SINGLETON;

    public static CallHierarchyUI getDefault() {
        if (SINGLETON == null) {
            SINGLETON = new CallHierarchyUI();
        }
        return SINGLETON;
    }

    public static IEditorPart isOpenInEditor(Object elem) {
        DartElement element = null;
        if (elem instanceof MethodWrapper) {
            element = ((MethodWrapper) elem).getMember();
        } else if (elem instanceof CallLocation) {
            element = ((CallLocation) elem).getCalledMember();
        }
        if (element != null) {
            return EditorUtility.isOpenInEditor(element);
        }
        return null;
    }

    public static void jumpToLocation(CallLocation callLocation) {
        try {
            IEditorPart methodEditor = DartUI.openInEditor(callLocation.getMember(), false, false);
            if (methodEditor instanceof ITextEditor) {
                ITextEditor editor = (ITextEditor) methodEditor;
                editor.selectAndReveal(callLocation.getStartPosition(),
                        (callLocation.getEndPosition() - callLocation.getStartPosition()));
            }
        } catch (DartModelException e) {
            DartToolsPlugin.log(e);
        } catch (PartInitException e) {
            DartToolsPlugin.log(e);
        }
    }

    public static void jumpToMember(DartElement element) {
        if (element != null) {
            try {
                DartUI.openInEditor(element, true, true);
            } catch (DartModelException e) {
                DartToolsPlugin.log(e);
            } catch (PartInitException e) {
                DartToolsPlugin.log(e);
            }
        }
    }

    /**
     * Opens the element in the editor or shows an error dialog if that fails.
     * 
     * @param element the element to open
     * @param shell parent shell for error dialog
     * @param activateOnOpen <code>true</code> if the editor should be activated
     * @return <code>true</code> iff no error occurred while trying to open the editor,
     *         <code>false</code> iff an error dialog was raised.
     */
    public static boolean openInEditor(Object element, Shell shell, boolean activateOnOpen) {
        CallLocation callLocation = CallHierarchy.getCallLocation(element);

        try {
            DartElement enclosingMember;
            int selectionStart;
            int selectionLength;

            if (callLocation != null) {
                enclosingMember = callLocation.getMember();
                selectionStart = callLocation.getStartPosition();
                selectionLength = callLocation.getEndPosition() - selectionStart;
            } else if (element instanceof MethodWrapper) {
                enclosingMember = ((MethodWrapper) element).getMember();
                SourceRange selectionRange = ((SourceReference) enclosingMember).getNameRange();
                if (selectionRange == null) {
                    selectionRange = ((SourceReference) enclosingMember).getSourceRange();
                }
                if (selectionRange == null) {
                    return true;
                }
                selectionStart = selectionRange.getOffset();
                selectionLength = selectionRange.getLength();
            } else {
                return true;
            }

            IEditorPart methodEditor = DartUI.openInEditor(enclosingMember, activateOnOpen, false);
            if (methodEditor instanceof ITextEditor) {
                ITextEditor editor = (ITextEditor) methodEditor;
                editor.selectAndReveal(selectionStart, selectionLength);
            }
            return true;
        } catch (DartModelException e) {
            DartToolsPlugin.log(
                    new Status(IStatus.ERROR, DartToolsPlugin.getPluginId(), DartStatusConstants.INTERNAL_ERROR,
                            CallHierarchyMessages.CallHierarchyUI_open_in_editor_error_message, e));

            ErrorDialog.openError(shell, CallHierarchyMessages.OpenLocationAction_error_title,
                    CallHierarchyMessages.CallHierarchyUI_open_in_editor_error_message, e.getStatus());
            return false;
        } catch (PartInitException x) {
            String name;
            if (callLocation != null) {
                name = callLocation.getCalledMember().getElementName();
            } else if (element instanceof MethodWrapper) {
                name = ((MethodWrapper) element).getName();
            } else {
                name = ""; //$NON-NLS-1$
            }
            MessageDialog.openError(shell, CallHierarchyMessages.OpenLocationAction_error_title,
                    Messages.format(CallHierarchyMessages.CallHierarchyUI_open_in_editor_error_messageArgs,
                            new String[] { name, x.getMessage() }));
            return false;
        }
    }

    public static CallHierarchyViewPart openSelectionDialog(DartElement[] candidates, IWorkbenchWindow window) {
        Assert.isTrue(candidates != null);

        DartElement input = null;
        if (candidates.length > 1) {
            String title = CallHierarchyMessages.CallHierarchyUI_selectionDialog_title;
            String message = CallHierarchyMessages.CallHierarchyUI_selectionDialog_message;
            input = SelectionConverter.selectJavaElement(candidates, window.getShell(), title, message);
        } else if (candidates.length == 1) {
            input = candidates[0];
        }
        if (input == null) {
            return openView(new TypeMember[] {}, window);
        }

        return openView(new DartElement[] { input }, window);
    }

    public static CallHierarchyViewPart openView(DartElement[] input, IWorkbenchWindow window) {
        if (input.length == 0) {
            MessageDialog.openInformation(window.getShell(),
                    CallHierarchyMessages.CallHierarchyUI_selectionDialog_title,
                    CallHierarchyMessages.CallHierarchyUI_open_operation_unavialable);
            return null;
        }
        IWorkbenchPage page = window.getActivePage();
        try {
            CallHierarchyViewPart viewPart = getDefault().findLRUCallHierarchyViewPart(page); //find the first view which is not pinned
            String secondaryId = null;
            if (viewPart == null) {
                if (page.findViewReference(CallHierarchyViewPart.ID_CALL_HIERARCHY) != null) {
                    secondaryId = String.valueOf(++getDefault().fViewCount);
                }
            } else {
                secondaryId = viewPart.getViewSite().getSecondaryId();
            }
            viewPart = (CallHierarchyViewPart) page.showView(CallHierarchyViewPart.ID_CALL_HIERARCHY, secondaryId,
                    IWorkbenchPage.VIEW_ACTIVATE);
            viewPart.setInputElements(input);
            return viewPart;
        } catch (CoreException e) {
            ExceptionHandler.handle(e, window.getShell(), CallHierarchyMessages.CallHierarchyUI_error_open_view,
                    e.getMessage());
        }
        return null;
    }

    /**
     * Converts an ISelection (containing MethodWrapper instances) to an ISelection with the
     * MethodWrapper's replaced by their corresponding TypeMembers. If the selection contains elements
     * which are not MethodWrapper instances or not already TypeMember instances they are discarded.
     * 
     * @param selection The selection to convert.
     * @return An ISelection containing TypeMember's in place of MethodWrapper instances.
     */
    static ISelection convertSelection(ISelection selection) {
        if (selection.isEmpty()) {
            return selection;
        }

        if (selection instanceof IStructuredSelection) {
            IStructuredSelection structuredSelection = (IStructuredSelection) selection;
            List<DartElement> elements = new ArrayList<DartElement>();
            for (Iterator<?> iter = structuredSelection.iterator(); iter.hasNext();) {
                Object element = iter.next();
                if (element instanceof MethodWrapper) {
                    DartElement member = ((MethodWrapper) element).getMember();
                    if (member != null) {
                        elements.add(member);
                    }
                } else if (element instanceof DartElement) {
                    elements.add((DartElement) element);
                } else if (element instanceof CallLocation) {
                    DartElement member = ((CallLocation) element).getMember();
                    elements.add(member);
                }
            }
            return new StructuredSelection(elements);
        }
        return StructuredSelection.EMPTY;
    }

    private int fViewCount = 0;

    private final List<DartElement[]> fMethodHistory = new ArrayList<DartElement[]>();

    /**
     * List of the Call Hierarchy views in LRU order, where the most recently used view is at index 0.
     */
    private List<CallHierarchyViewPart> fLRUCallHierarchyViews = new ArrayList<CallHierarchyViewPart>();

    private CallHierarchyUI() {
        // Do nothing
    }

    /**
     * Returns the maximum tree level allowed
     */
    public int getMaxCallDepth() {
        IPreferenceStore settings = DartToolsPlugin.getDefault().getPreferenceStore();
        int maxCallDepth = settings.getInt(PREF_MAX_CALL_DEPTH);
        if (maxCallDepth < 1 || maxCallDepth > 99) {
            maxCallDepth = DEFAULT_MAX_CALL_DEPTH;
        }
        return maxCallDepth;
    }

    public void setMaxCallDepth(int maxCallDepth) {
        IPreferenceStore settings = DartToolsPlugin.getDefault().getPreferenceStore();
        settings.setValue(PREF_MAX_CALL_DEPTH, maxCallDepth);
    }

    /**
     * Adds the activated view part to the head of the list.
     * 
     * @param view the Call Hierarchy view part
     */
    void callHierarchyViewActivated(CallHierarchyViewPart view) {
        fLRUCallHierarchyViews.remove(view);
        fLRUCallHierarchyViews.add(0, view);
    }

    /**
     * Removes the closed view part from the list.
     * 
     * @param view the closed view part
     */
    void callHierarchyViewClosed(CallHierarchyViewPart view) {
        fLRUCallHierarchyViews.remove(view);
    }

    /**
     * Clears the history and updates all the open views.
     */
    void clearHistory() {
        for (Iterator<CallHierarchyViewPart> iter = fLRUCallHierarchyViews.iterator(); iter.hasNext();) {
            CallHierarchyViewPart part = iter.next();
            part.setHistoryEntries(new TypeMember[0][]);
            part.setInputElements(null);
        }
    }

    /**
     * Returns the method history.
     * 
     * @return the method history
     */
    List<DartElement[]> getMethodHistory() {
        return fMethodHistory;
    }

    /**
     * Finds the first Call Hierarchy view part instance that is not pinned.
     * 
     * @param page the active page
     * @return the Call Hierarchy view part to open or <code>null</code> if none found
     */
    private CallHierarchyViewPart findLRUCallHierarchyViewPart(IWorkbenchPage page) {
        boolean viewFoundInPage = false;
        for (Iterator<CallHierarchyViewPart> iter = fLRUCallHierarchyViews.iterator(); iter.hasNext();) {
            CallHierarchyViewPart view = iter.next();
            if (page.equals(view.getSite().getPage())) {
                if (!view.isPinned()) {
                    return view;
                }
                viewFoundInPage = true;
            }
        }
        if (!viewFoundInPage) {
            // find unresolved views
            IViewReference[] viewReferences = page.getViewReferences();
            for (int i = 0; i < viewReferences.length; i++) {
                IViewReference curr = viewReferences[i];
                if (CallHierarchyViewPart.ID_CALL_HIERARCHY.equals(curr.getId()) && page.equals(curr.getPage())) {
                    CallHierarchyViewPart view = (CallHierarchyViewPart) curr.getView(true);
                    if (view != null && !view.isPinned()) {
                        return view;
                    }
                }
            }
        }
        return null;
    }
}