org.eclipse.ant.internal.ui.editor.outline.AntEditorContentOutlinePage.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ant.internal.ui.editor.outline.AntEditorContentOutlinePage.java

Source

/*******************************************************************************
 * Copyright (c) 2002, 2016 GEBIT Gesellschaft fuer EDV-Beratung
 * und Informatik-Technologien mbH, 
 * Berlin, Duesseldorf, Frankfurt (Germany) 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:
 *     GEBIT Gesellschaft fuer EDV-Beratung und Informatik-Technologien mbH - initial API and implementation
 *       IBM Corporation - bug fixes
 *     John-Mason P. Shackelford (john-mason.shackelford@pearson.com) - bug 49380, bug 34548, bug 53547
 *******************************************************************************/

package org.eclipse.ant.internal.ui.editor.outline;

import java.util.List;

import org.eclipse.ant.internal.ui.AntUIPlugin;
import org.eclipse.ant.internal.ui.IAntUIConstants;
import org.eclipse.ant.internal.ui.IAntUIPreferenceConstants;
import org.eclipse.ant.internal.ui.editor.AntEditor;
import org.eclipse.ant.internal.ui.editor.actions.TogglePresentationAction;
import org.eclipse.ant.internal.ui.model.AntElementNode;
import org.eclipse.ant.internal.ui.model.AntImportNode;
import org.eclipse.ant.internal.ui.model.AntModel;
import org.eclipse.ant.internal.ui.model.AntModelChangeEvent;
import org.eclipse.ant.internal.ui.model.AntModelContentProvider;
import org.eclipse.ant.internal.ui.model.AntModelCore;
import org.eclipse.ant.internal.ui.model.AntModelLabelProvider;
import org.eclipse.ant.internal.ui.model.AntProjectNode;
import org.eclipse.ant.internal.ui.model.AntPropertyNode;
import org.eclipse.ant.internal.ui.model.AntTargetNode;
import org.eclipse.ant.internal.ui.model.AntTaskNode;
import org.eclipse.ant.internal.ui.model.IAntModel;
import org.eclipse.ant.internal.ui.model.IAntModelListener;
import org.eclipse.ant.internal.ui.views.actions.AntOpenWithMenu;

import org.eclipse.core.resources.IFile;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.ListenerList;

import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;

import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;

import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.part.IShowInSource;
import org.eclipse.ui.part.ShowInContext;

import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;

import org.eclipse.ui.views.contentoutline.ContentOutlinePage;

/**
 * Content outline page for the Ant Editor.
 */
public class AntEditorContentOutlinePage extends ContentOutlinePage implements IShowInSource, IAdaptable {

    private static final int EXPAND_TO_LEVEL = 2;

    private Menu fMenu;
    private AntOpenWithMenu fOpenWithMenu;

    private IAntModelListener fListener;
    private IAntModel fModel;
    private AntModelCore fCore;
    private ListenerList<ISelectionChangedListener> fPostSelectionChangedListeners = new ListenerList<>();
    private boolean fIsModelEmpty = true;
    private boolean fFilterInternalTargets;
    private boolean fFilterImportedElements;
    private boolean fFilterProperties;
    private boolean fFilterTopLevel;
    private boolean fSort;

    private ViewerComparator fComparator;

    private AntEditor fEditor;

    private TogglePresentationAction fTogglePresentation;

    /**
     * A viewer filter for the Ant Content Outline
     */
    private class AntOutlineFilter extends ViewerFilter {

        @Override
        public boolean select(Viewer viewer, Object parentElement, Object element) {
            if (element instanceof AntElementNode) {
                AntElementNode node = (AntElementNode) element;
                if (fFilterTopLevel && (node instanceof AntTaskNode && parentElement instanceof AntProjectNode)) {
                    return false;
                }
                if (fFilterImportedElements && (node.getImportNode() != null || node.isExternal())) {
                    if (node instanceof AntTargetNode && ((AntTargetNode) node).isDefaultTarget()) {
                        return true;
                    }
                    return false;
                }
                if (fFilterInternalTargets && node instanceof AntTargetNode) {
                    return !((AntTargetNode) node).isInternal();
                }
                if (fFilterProperties && node instanceof AntPropertyNode) {
                    return false;
                }
                if (!node.isStructuralNode()) {
                    return false;
                }
            }
            return true;
        }
    }

    private class AntOutlineComparator extends ViewerComparator {
        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
         */
        @Override
        public int compare(Viewer viewer, Object e1, Object e2) {
            if (!(e1 instanceof AntElementNode && e2 instanceof AntElementNode)) {
                return super.compare(viewer, e1, e2);
            }
            String name1 = ((AntElementNode) e1).getLabel();
            String name2 = ((AntElementNode) e2).getLabel();
            return getComparator().compare(name1, name2);
        }
    }

    /**
     * Sets whether internal targets should be filtered out of the outline.
     * 
     * @param filter
     *            whether or not internal targets should be filtered out
     */
    protected void setFilterInternalTargets(boolean filter) {
        fFilterInternalTargets = filter;
        setFilter(filter, IAntUIPreferenceConstants.ANTEDITOR_FILTER_INTERNAL_TARGETS);
    }

    /**
     * Sets whether imported elements should be filtered out of the outline.
     * 
     * @param filter
     *            whether or not imported elements should be filtered out
     */
    protected void setFilterImportedElements(boolean filter) {
        fFilterImportedElements = filter;
        setFilter(filter, IAntUIPreferenceConstants.ANTEDITOR_FILTER_IMPORTED_ELEMENTS);
    }

    private void setFilter(boolean filter, String name) {
        if (name != null) {
            AntUIPlugin.getDefault().getPreferenceStore().setValue(name, filter);
        }
        // filter has been changed
        getTreeViewer().refresh();
    }

    /**
     * Sets whether properties should be filtered out of the outline.
     * 
     * @param filter
     *            whether or not properties should be filtered out
     */
    protected void setFilterProperties(boolean filter) {
        fFilterProperties = filter;
        setFilter(filter, IAntUIPreferenceConstants.ANTEDITOR_FILTER_PROPERTIES);
    }

    /**
     * Sets whether internal targets should be filtered out of the outline.
     * 
     * @param filter
     *            whether or not internal targets should be filtered out
     */
    protected void setFilterTopLevel(boolean filter) {
        fFilterTopLevel = filter;
        setFilter(filter, IAntUIPreferenceConstants.ANTEDITOR_FILTER_TOP_LEVEL);
    }

    /**
     * Returns whether internal targets are currently being filtered out of the outline.
     * 
     * @return whether or not internal targets are being filtered out
     */
    protected boolean filterInternalTargets() {
        return fFilterInternalTargets;
    }

    /**
     * Returns whether imported elements are currently being filtered out of the outline.
     * 
     * @return whether or not imported elements are being filtered out
     */
    protected boolean filterImportedElements() {
        return fFilterImportedElements;
    }

    /**
     * Returns whether properties are currently being filtered out of the outline.
     * 
     * @return whether or not properties are being filtered out
     */
    protected boolean filterProperties() {
        return fFilterProperties;
    }

    /**
     * Returns whether top level tasks/types are currently being filtered out of the outline.
     * 
     * @return whether or not top level tasks/types are being filtered out
     */
    protected boolean filterTopLevel() {
        return fFilterTopLevel;
    }

    /**
     * Sets whether elements should be sorted in the outline.
     * 
     * @param sort
     *            whether or not elements should be sorted
     */
    protected void setSort(boolean sort) {
        fSort = sort;
        if (sort) {
            if (fComparator == null) {
                fComparator = new AntOutlineComparator();
            }
            getTreeViewer().setComparator(fComparator);
        } else {
            getTreeViewer().setComparator(null);
        }
        AntUIPlugin.getDefault().getPreferenceStore().setValue(IAntUIPreferenceConstants.ANTEDITOR_SORT, sort);
    }

    /**
     * Returns whether elements are currently being sorted.
     * 
     * @return whether elements are currently being sorted
     */
    protected boolean isSort() {
        return fSort;
    }

    /**
     * Creates a new AntEditorContentOutlinePage.
     */
    public AntEditorContentOutlinePage(AntModelCore core, AntEditor editor) {
        super();
        fCore = core;
        fFilterInternalTargets = AntUIPlugin.getDefault().getPreferenceStore()
                .getBoolean(IAntUIPreferenceConstants.ANTEDITOR_FILTER_INTERNAL_TARGETS);
        fFilterImportedElements = AntUIPlugin.getDefault().getPreferenceStore()
                .getBoolean(IAntUIPreferenceConstants.ANTEDITOR_FILTER_IMPORTED_ELEMENTS);
        fFilterProperties = AntUIPlugin.getDefault().getPreferenceStore()
                .getBoolean(IAntUIPreferenceConstants.ANTEDITOR_FILTER_PROPERTIES);
        fFilterTopLevel = AntUIPlugin.getDefault().getPreferenceStore()
                .getBoolean(IAntUIPreferenceConstants.ANTEDITOR_FILTER_TOP_LEVEL);
        fSort = AntUIPlugin.getDefault().getPreferenceStore().getBoolean(IAntUIPreferenceConstants.ANTEDITOR_SORT);
        fEditor = editor;

        fTogglePresentation = new TogglePresentationAction();
        fTogglePresentation.setEditor(editor);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.part.IPage#dispose()
     */
    @Override
    public void dispose() {
        if (fMenu != null) {
            fMenu.dispose();
        }
        if (fOpenWithMenu != null) {
            fOpenWithMenu.dispose();
        }
        if (fListener != null) {
            fCore.removeAntModelListener(fListener);
            fListener = null;
        }
        fTogglePresentation.setEditor(null);

        super.dispose();
    }

    /**
     * Creates the control (outline view) for this page
     */
    @Override
    public void createControl(Composite parent) {
        super.createControl(parent);

        TreeViewer viewer = getTreeViewer();

        viewer.setContentProvider(new AntModelContentProvider());
        setSort(fSort);

        viewer.setLabelProvider(new AntModelLabelProvider());
        viewer.addFilter(new AntOutlineFilter());
        if (fModel != null) {
            setViewerInput(fModel);
        }

        MenuManager manager = new MenuManager("#PopUp"); //$NON-NLS-1$
        manager.setRemoveAllWhenShown(true);
        manager.addMenuListener(new IMenuListener() {
            @Override
            public void menuAboutToShow(IMenuManager menuManager) {
                contextMenuAboutToShow(menuManager);
            }
        });
        fMenu = manager.createContextMenu(viewer.getTree());
        viewer.getTree().setMenu(fMenu);

        IPageSite site = getSite();
        site.registerContextMenu(IAntUIConstants.PLUGIN_ID + ".antEditorOutline", manager, viewer); //$NON-NLS-1$

        IToolBarManager tbm = site.getActionBars().getToolBarManager();
        tbm.add(new ToggleSortAntOutlineAction(this));
        tbm.add(new FilterInternalTargetsAction(this));
        tbm.add(new FilterPropertiesAction(this));
        tbm.add(new FilterImportedElementsAction(this));
        tbm.add(new FilterTopLevelAction(this));

        IMenuManager viewMenu = site.getActionBars().getMenuManager();
        viewMenu.add(new ToggleLinkWithEditorAction(fEditor));

        fOpenWithMenu = new AntOpenWithMenu(this.getSite().getPage());

        viewer.addPostSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(SelectionChangedEvent event) {
                firePostSelectionChanged(event.getSelection());
            }
        });

        site.getActionBars().setGlobalActionHandler(
                ITextEditorActionDefinitionIds.TOGGLE_SHOW_SELECTED_ELEMENT_ONLY, fTogglePresentation);
    }

    private void setViewerInput(Object newInput) {
        TreeViewer tree = getTreeViewer();
        Object oldInput = tree.getInput();

        boolean isAntModel = (newInput instanceof AntModel);
        boolean wasAntModel = (oldInput instanceof AntModel);

        if (isAntModel && !wasAntModel) {
            if (fListener == null) {
                fListener = createAntModelChangeListener();
            }
            fCore.addAntModelListener(fListener);
        } else if (!isAntModel && wasAntModel && fListener != null) {
            fCore.removeAntModelListener(fListener);
            fListener = null;
        }

        tree.setInput(newInput);

        if (isAntModel) {
            updateTreeExpansion();
        }
    }

    public void setPageInput(AntModel xmlModel) {
        fModel = xmlModel;
        if (getTreeViewer() != null) {
            setViewerInput(fModel);
        }
    }

    private IAntModelListener createAntModelChangeListener() {
        return new IAntModelListener() {
            @Override
            public void antModelChanged(final AntModelChangeEvent event) {
                if (event.getModel() == fModel && !getControl().isDisposed()) {
                    getControl().getDisplay().asyncExec(new Runnable() {
                        @Override
                        public void run() {
                            Control ctrl = getControl();
                            if (ctrl != null && !ctrl.isDisposed()) {
                                getTreeViewer().refresh();
                                updateTreeExpansion();
                            }
                        }
                    });
                }
            }
        };
    }

    public void addPostSelectionChangedListener(ISelectionChangedListener listener) {
        fPostSelectionChangedListeners.add(listener);
    }

    public void removePostSelectionChangedListener(ISelectionChangedListener listener) {
        fPostSelectionChangedListeners.remove(listener);
    }

    private void updateTreeExpansion() {
        boolean wasModelEmpty = fIsModelEmpty;
        fIsModelEmpty = fModel == null || fModel.getProjectNode() == null;
        if (wasModelEmpty && !fIsModelEmpty) {
            getTreeViewer().expandToLevel(EXPAND_TO_LEVEL);
        }
    }

    private void firePostSelectionChanged(ISelection selection) {
        // create an event
        SelectionChangedEvent event = new SelectionChangedEvent(this, selection);

        // fire the event
        for (ISelectionChangedListener iSelectionChangedListener : fPostSelectionChangedListeners) {
            iSelectionChangedListener.selectionChanged(event);
        }
    }

    private void contextMenuAboutToShow(IMenuManager menuManager) {
        if (shouldAddOpenWithMenu()) {
            addOpenWithMenu(menuManager);
        }
        menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
    }

    private void addOpenWithMenu(IMenuManager menuManager) {
        AntElementNode element = getSelectedNode();
        IFile file = null;
        if (element != null) {
            file = element.getIFile();
        }
        if (file != null) {
            menuManager.add(new Separator("group.open")); //$NON-NLS-1$
            IMenuManager submenu = new MenuManager(AntOutlineMessages.AntEditorContentOutlinePage_Open_With_1);
            fOpenWithMenu.setNode(element);
            submenu.add(fOpenWithMenu);
            menuManager.appendToGroup("group.open", submenu); //$NON-NLS-1$
        }
    }

    private boolean shouldAddOpenWithMenu() {
        AntElementNode node = getSelectedNode();
        if (node instanceof AntImportNode) {
            return true;
        }
        if (node != null && node.isExternal()) {
            String path = node.getFilePath();
            if (path != null && path.length() > 0) {
                return true;
            }
        }
        return false;
    }

    private AntElementNode getSelectedNode() {
        ISelection iselection = getSelection();
        if (iselection instanceof IStructuredSelection) {
            IStructuredSelection selection = (IStructuredSelection) iselection;
            if (selection.size() == 1) {
                Object selected = selection.getFirstElement();
                if (selected instanceof AntElementNode) {
                    return (AntElementNode) selected;
                }
            }
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
     */
    @SuppressWarnings("unchecked")
    @Override
    public <T> T getAdapter(Class<T> key) {
        if (key == IShowInSource.class) {
            return (T) this;
        }
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.part.IShowInSource#getShowInContext()
     */
    @Override
    public ShowInContext getShowInContext() {
        IFile file = null;
        if (fModel != null) {
            AntElementNode node = getSelectedNode();
            if (node != null) {
                file = node.getIFile();
            }
        }
        if (file != null) {
            ISelection selection = new StructuredSelection(file);
            return new ShowInContext(null, selection);
        }
        return null;
    }

    public void select(AntElementNode node) {
        if (getTreeViewer() != null) {
            ISelection s = getTreeViewer().getSelection();
            if (s instanceof IStructuredSelection) {
                IStructuredSelection ss = (IStructuredSelection) s;
                List<?> nodes = ss.toList();
                if (!nodes.contains(node)) {
                    s = (node == null ? StructuredSelection.EMPTY : new StructuredSelection(node));
                    getTreeViewer().setSelection(s, true);
                }
            }
        }
    }
}