org.cfeclipse.cfml.views.contentoutline.CFContentOutlineView.java Source code

Java tutorial

Introduction

Here is the source code for org.cfeclipse.cfml.views.contentoutline.CFContentOutlineView.java

Source

/*
 * Created on Apr 6, 2004
 *
 * The MIT License
 * Copyright (c) 2004 Rob Rohan
 *
 * Permission is hereby granted, free of charge, to any person obtaining a 
 * copy of this software and associated documentation files (the "Software"), 
 * to deal in the Software without restriction, including without limitation 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 * and/or sell copies of the Software, and to permit persons to whom the Software 
 * is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 * SOFTWARE.
 */
package org.cfeclipse.cfml.views.contentoutline;

//import org.eclipse.core.resources.IResource;
import java.util.Iterator;

import org.cfeclipse.cfml.editors.CFMLEditor;
import org.cfeclipse.cfml.editors.ICFDocument;
import org.cfeclipse.cfml.editors.actions.GotoFileAction;
import org.cfeclipse.cfml.parser.CFDocument;
import org.cfeclipse.cfml.parser.CFNodeList;
import org.cfeclipse.cfml.parser.docitems.DocItem;
import org.cfeclipse.cfml.parser.docitems.ScriptItem;
import org.cfeclipse.cfml.parser.docitems.TagItem;
import org.cfeclipse.cfml.util.CFPluginImages;
import org.eclipse.jface.action.Action;
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.dialogs.InputDialog;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.ui.views.contentoutline.ContentOutlinePage;

/**
 * @author Rob
 * 
 *         This is the default content outline view
 */
public class CFContentOutlineView extends ContentOutlinePage
        implements IPartListener, IPropertyListener, ISelectionListener {
    public static final String ID_CONTENTOUTLINE = "org.cfeclipse.cfml.views.contentoutline.cfcontentoutlineview";
    private static final int EXPAND_TO_LEVEL = 2;
    protected Action jumpAction, selectAction, deleteItem, expandAction, collapseAction, filterOnAction, openAction,
            removeFilters;
    protected Action filters[];
    private boolean fSelectionFromEditor = false;
    private static String filter = "";
    protected static GotoFileAction gfa = new GotoFileAction();

    public void createControl(Composite parent) {
        super.createControl(parent);
        DocItem root = getRootInput();
        TreeViewer viewer = getTreeViewer();
        viewer.setContentProvider(new OutlineContentProvider(root));
        viewer.setLabelProvider(new OutlineLabelProvider());
        viewer.addSelectionChangedListener(this);
        // this listener listens to the editor (vs. this outline view)
        getSite().getPage().addPostSelectionListener(this);
        createActions();
        createToolbar();
        createContextMenu();
        hookGlobalActions();
        hookDoubleClickAction();
        reload(root);
    }

    protected void fireSelectionChanged(ISelection selection) {
        System.out.println("wee");
    }

    /**
     * Gets a 1 level tree of items in the document of a type. See the parser
     * for the filter syntax
     * 
     * @param filter
     * @return
     */
    public DocItem getItems(String filter) {
        DocItem scratch = new TagItem(1, 1, 1, "root");

        DocItem rootItem = getRootInput();
        CFNodeList nodes = rootItem.selectNodes(filter);

        Iterator i = nodes.iterator();
        while (i.hasNext()) {
            try {
                scratch.addChild((DocItem) i.next());
            } catch (Exception e) {
                System.err.println("Tree item set error ");
                e.printStackTrace();
            }
        }

        return scratch;
    }

    /**
     * Gets the root element of the document. Saves information into a local
     * cache so if there is an error in the parser it uses the last known good
     * outline (which kind of sucks but it looks better)
     * 
     * @return the root directory
     */
    public DocItem getRootInput() {
        try {
            DocItem docRoot = null;

            IEditorPart iep = getSite().getPage().getActiveEditor();

            iep.addPropertyListener(this);
            getSite().getPage().addPartListener(this);

            ITextEditor ite = (ITextEditor) iep;
            ICFDocument icfd = null;
            CFDocument cfd = null;
            if (ite.getDocumentProvider().getDocument(iep.getEditorInput()) instanceof ICFDocument) {
                icfd = (ICFDocument) ite.getDocumentProvider().getDocument(iep.getEditorInput());
                cfd = icfd.getCFDocument();
            }
            // icfd.clearAllMarkers();
            // icfd.parseDocument();

            if (cfd != null) {
                docRoot = cfd.getDocumentRoot();
                // lastDocRoot = docRoot;
            }

            if (docRoot != null) {
                return docRoot;
            } else {
                return createFakeRoot();
            }
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }

        // a fake root
        return createFakeRoot();
    }

    private TagItem createFakeRoot() {
        TagItem tg = new TagItem(1, 1, 1, "Unk");
        return tg;
    }

    /**
     * gets the currently selected item in docitem form or <code>null</code> if
     * there is none
     * 
     * @return
     */
    private Iterator getSelectedDocItems() {
        Iterator selecteditem = null;

        // can't do much if nothing is selected
        if (getTreeViewer().getSelection().isEmpty()) {
            return null;
        } else {
            IStructuredSelection selection = (IStructuredSelection) getTreeViewer().getSelection();
            selecteditem = selection.iterator();
        }

        return selecteditem;
    }

    /**
     * gets the currently selected item in docitem form or <code>null</code> if
     * there is none
     * 
     * @return
     */
    private DocItem getSelectedDocItem() {
        Iterator selecteditems = getSelectedDocItems();

        // can't do much if nothing is selected
        if (selecteditems == null || !selecteditems.hasNext()) {
            return null;
        }
        return (DocItem) selecteditems.next();
    }

    /**
     * for recursive parent expansion in setSelectedDocItem
     * 
     * @return
     */
    private void expandParentItems(DocItem item) {
        // can't do much if nothing is selected
        DocItem parentItem = item.getParent();
        if (parentItem != null) {
            TreeViewer tree = getTreeViewer();
            tree.setExpandedState(parentItem, true);
            tree.refresh(parentItem, false);
            expandParentItems(parentItem);
        }
    }

    /**
     * sets the currently selected item in docitem form or <code>null</code> if
     * there is none
     * @return
     */
    private void setSelectedDocItem(DocItem item) {
        // can't do much if nothing is selected
        if (item != null) {
            TreeViewer tree = getTreeViewer();
            fSelectionFromEditor = true;
            tree.setSelection(new StructuredSelection(item), false);
            fSelectionFromEditor = false;
            //tree.refresh(item, false);
            tree.setExpandedState(item, true);
            tree.reveal(item);
            // reveal takes care of this. Doh!
            //expandParentItems(item);
        }
    }

    /**
     * Selects the item(s) within the source code view
     */
    protected void selectItem() {
        // get a handle to the current editor and assign it to our temp action
        IEditorPart iep = getSite().getPage().getActiveEditor();
        Iterator selecteditems = getSelectedDocItems();

        if (!selecteditems.hasNext())
            return;

        ITextEditor editor = (ITextEditor) iep;
        DocItem firstItem = ((DocItem) selecteditems.next());
        int startPos = firstItem.getStartPosition();
        int endPos = firstItem.getEndPosition();
        if (!selecteditems.hasNext()) {
            // select whole tag
            if (firstItem.getClass().getName().endsWith("CfmlComment")) {
                editor.selectAndReveal(firstItem.getStartPosition(),
                        firstItem.getEndPosition() - firstItem.getStartPosition() + 1);
                return;
            }
            if (firstItem instanceof TagItem) {
                TagItem cti = (TagItem) firstItem;
                if (cti.matchingItem != null) {
                    if (cti.matchingItem.getStartPosition() < cti.getStartPosition()) {
                        startPos = cti.matchingItem.getStartPosition();
                        endPos = cti.getEndPosition();
                    } else {
                        startPos = cti.getStartPosition();
                        endPos = cti.matchingItem.getEndPosition();
                    }
                } else {
                    startPos = cti.getStartPosition();
                    endPos = cti.getEndPosition();
                }
            } else {
                ScriptItem csi = (ScriptItem) firstItem;
                startPos = csi.getStartPosition();
                endPos = csi.getEndPosition();
            }
        } else {
            // otherwise select selected items
            while (selecteditems.hasNext()) {
                endPos = ((DocItem) selecteditems.next()).getEndPosition();
            }
        }
        editor.selectAndReveal(startPos, endPos - startPos + 1);
    }

    /**
     * Gets the selected item parses it, and adds the defined stuff to the
     * editor
     */
    protected void jumpToItem() {
        // get a handle to the current editor and assign it to our temp action
        IEditorPart iep = getSite().getPage().getActiveEditor();
        DocItem selecteditem = getSelectedDocItem();

        if (selecteditem == null)
            return;

        ITextEditor editor = (ITextEditor) iep;
        // editor.setHighlightRange(selecteditem.getStartPosition(),selecteditem.getMatchingItem().getEndPosition(),true);
        editor.setHighlightRange(selecteditem.getStartPosition(), 0, true);
    }

    /**
     * filters the outline on the currenly selected element
     */
    protected void filterOnSelected() {
        DocItem selecteditem = getSelectedDocItem();

        if (selecteditem == null)
            return;

        filter = "//" + selecteditem.getName();
        reload();
    }

    public void reload(DocItem root) {
        // saveExpandedElements();
        getTreeViewer().setInput(root);
        if (filter.length() == 0) {
            removeFilters.setEnabled(false);
        } else {
            removeFilters.setEnabled(true);
        }
        getControl().getDisplay().asyncExec(new Runnable() {
            public void run() {
                Control ctrl = getControl();
                if (ctrl != null && !ctrl.isDisposed()) {
                    getTreeViewer().refresh();
                    updateTreeExpansion();
                }
            }
        });
    }

    public void reload() {
        if (filter.length() == 0) {
            DocItem di = getRootInput();
            reload(di);
        } else {
            reload(getItems(filter));
        }
    }

    private void updateTreeExpansion() {
        DocItem root = getRootInput();
        if (!getTreeViewer().getExpandedState(root) && root.hasChildren()
                && root.getFirstChild().getName().compareToIgnoreCase("cfcomponent") == 0) {
            getTreeViewer().setExpandedState(root.getFirstChild(), true);
            getTreeViewer().refresh(root, false);
        }
        //      boolean wasModelEmpty= fIsModelEmpty;
        //      fIsModelEmpty= fModel == null || fModel.getProjectNode() == null;
        //      if (wasModelEmpty && !fIsModelEmpty) {
        //         getTreeViewer().expandToLevel(EXPAND_TO_LEVEL);
        //      }
    }

    /**
     * creates all the default actions
     */
    protected void createActions() {
        jumpAction = new Action("Jump To",
                CFPluginImages.getImageRegistry().getDescriptor(CFPluginImages.ICON_SHOW)) {
            public void run() {
                // we only want to jump if the change came from tree viewer
                // selection
                jumpToItem();
            }
        };
        jumpAction.setToolTipText("Jump to selected tag in the editor");

        selectAction = new Action("Select",
                CFPluginImages.getImageRegistry().getDescriptor(CFPluginImages.ICON_SHOW)) {
            public void run() {
                selectItem();
            }
        };
        selectAction.setToolTipText("Select tag in the editor");

        filterOnAction = new Action("Filter On This",
                CFPluginImages.getImageRegistry().getDescriptor(CFPluginImages.ICON_TAG)) {
            public void run() {
                filterOnSelected();
            }
        };
        filterOnAction.setToolTipText("Filter on selected tag type");

        expandAction = new Action("Expand All", AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.search",
                "$nl$/icons/full/elcl16/expandall.gif")) {
            public void run() {
                getTreeViewer().expandAll();
            }
        };
        expandAction.setToolTipText("Expand all");

        collapseAction = new Action("Collapse All", AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.search",
                "$nl$/icons/full/elcl16/collapseall.gif")) {
            public void run() {
                getTreeViewer().collapseAll();
            }
        };
        collapseAction.setToolTipText("Collapse all");

        openAction = new Action("Open File",
                CFPluginImages.getImageRegistry().getDescriptor(CFPluginImages.ICON_IMPORT)) {
            public void run() {
                openFile();
            }
        };

        removeFilters = new Action("Remove Filter",
                CFPluginImages.getImageRegistry().getDescriptor(CFPluginImages.ICON_DELETE)) {
            public void run() {
                filter = "";
                reload();
            }
        };
        removeFilters.setToolTipText("Remove Filter");

        deleteItem = new Action("Delete Item",
                CFPluginImages.getImageRegistry().getDescriptor(CFPluginImages.ICON_DELETE)) {
            public void run() {
                // this doesn't do nothing
                System.out.println("this should delete");
            }
        };

        // /filters
        filters = new Action[6];

        filters[0] = new Action("Include",
                CFPluginImages.getImageRegistry().getDescriptor(CFPluginImages.ICON_TAG)) {
            public void run() {
                filter = "//cfinclude";
                reload(getItems(filter));
            }
        };

        filters[1] = new Action("Module",
                CFPluginImages.getImageRegistry().getDescriptor(CFPluginImages.ICON_TAG)) {
            public void run() {
                filter = "//cfmodule";
                reload(getItems(filter));
            }
        };

        filters[2] = new Action("Query", CFPluginImages.getImageRegistry().getDescriptor(CFPluginImages.ICON_TAG)) {
            public void run() {
                filter = "//cfquery";
                reload(getItems(filter));
            }
        };

        filters[3] = new Action("Set", CFPluginImages.getImageRegistry().getDescriptor(CFPluginImages.ICON_TAG)) {
            public void run() {
                filter = "//cfset";
                reload(getItems(filter));
            }
        };

        filters[4] = new Action("Case", CFPluginImages.getImageRegistry().getDescriptor(CFPluginImages.ICON_TAG)) {
            public void run() {
                filter = "//cfcase";
                reload(getItems(filter));
            }
        };

        filters[5] = new Action("Custom",
                CFPluginImages.getImageRegistry().getDescriptor(CFPluginImages.ICON_TAG)) {
            public void run() {
                InputDialog pathdialog = new InputDialog(getSite().getShell(), "CFML Path Filter",
                        "Filter outline using path (i.e. \"//cfoutput\" for all the cfoutput tags):", "", null);

                if (pathdialog.open() == org.eclipse.jface.window.Window.OK) {
                    String xpath = pathdialog.getValue();
                    if (xpath.length() > 0) {
                        filter = xpath;
                        reload(getItems(filter));
                    }
                }
            }
        };
    }

    private void createContextMenu() {
        // Create menu manager.
        MenuManager menuMgr = new MenuManager();
        menuMgr.setRemoveAllWhenShown(true);
        menuMgr.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager mgr) {
                fillContextMenu(mgr);
            }
        });

        // Create menu.
        Menu menu = menuMgr.createContextMenu(getTreeViewer().getControl());
        getTreeViewer().getControl().setMenu(menu);
    }

    private void fillContextMenu(IMenuManager mgr) {
        mgr.add(selectAction);
        mgr.add(new Separator());
        mgr.add(filterOnAction);
        DocItem di = getSelectedDocItem();
        if (di != null) {
            String sname = di.getName();
            if (filter.length() > 0) {
                mgr.add(removeFilters);
            }
            if (sname.equals("cfinclude") || sname.equals("cfmodule")) {
                mgr.add(openAction);
            }
        }
        mgr.add(new Separator());
        int flen = filters.length;
        for (int i = 0; i < flen; i++) {
            mgr.add(filters[i]);
        }

    }

    protected void createToolbar() {
        IToolBarManager toolbarManager = super.getSite().getActionBars().getToolBarManager();
        toolbarManager.add(expandAction);
        toolbarManager.add(collapseAction);
        toolbarManager.add(selectAction);
        toolbarManager.add(filterOnAction);
        toolbarManager.add(removeFilters);
    }

    /**
     * method to open the currently selected docitem if its a include or a
     * module item
     */
    private void openFile() {
        IEditorPart iep = getSite().getPage().getActiveEditor();
        DocItem selecteditem = getSelectedDocItem();
        if (selecteditem == null)
            return;

        String si = selecteditem.getName();
        if (si.equalsIgnoreCase("cfinclude") || si.equalsIgnoreCase("cfmodule")) {
            gfa.setActiveEditor(null, iep);
            gfa.run(null);
        }
    }

    private void hookDoubleClickAction() {
        getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                selectAction.run();
            }
        });
    }

    private void hookGlobalActions() {
        IActionBars bars = getSite().getActionBars();
        bars.setGlobalActionHandler(IWorkbenchActionConstants.DELETE, deleteItem);
        getTreeViewer().getControl().addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent event) {
                if (event.character == SWT.DEL && event.stateMask == 0 && deleteItem.isEnabled()) {
                    deleteItem.run();
                }
            }
        });
    }

    public void selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent event) {
        // this fires when tree node selection changed
        if (!fSelectionFromEditor) {
            jumpAction.run();
        }
        // getTreeViewer().refresh(new
        // StructuredSelection(event.getSelection()));
    }

    public void selectionChanged(IWorkbenchPart workbench, ISelection selection) {
        // this fires when editor is changed (thanks to addPostSelection in
        // createControl)
        if (selection != null && selection instanceof ITextSelection) {
            IEditorPart curEditor = workbench.getSite().getWorkbenchWindow().getActivePage().getActiveEditor();
            if (curEditor != null && curEditor instanceof CFMLEditor) {
                CFMLEditor curDoc = (CFMLEditor) curEditor;
                DocItem tagItem = curDoc.getSelectionCursorListener().getSelectedTag();
                if (tagItem != null) {
                    setSelectedDocItem(tagItem);
                }
            }
        }
        //      if (!getControl().isDisposed()) {
        //         getControl().getDisplay().asyncExec(new Runnable() {
        //            public void run() {
        //               Control ctrl= getControl();
        //               if (ctrl != null && !ctrl.isDisposed()) {
        //                  reload();
        //                  getTreeViewer().refresh();
        //               }
        //            }
        //         });
        //      }
    }

    public void partActivated(IWorkbenchPart arg0) {
        // TODO Auto-generated method stub

    }

    public void partBroughtToTop(IWorkbenchPart arg0) {
        // TODO Auto-generated method stub

    }

    public void partClosed(IWorkbenchPart arg0) {
        // TODO Auto-generated method stub

    }

    public void partDeactivated(IWorkbenchPart arg0) {
        // TODO Auto-generated method stub

    }

    public void partOpened(IWorkbenchPart arg0) {
        // TODO Auto-generated method stub

    }

    public void propertyChanged(Object arg0, int arg1) {
        // this generally comes from a save.  When we get the reconciler going, shouldn't need it
        fSelectionFromEditor = true;
        reload();
    }

}