com.architexa.diagrams.relo.jdt.actions.OpenReloSessionTreeDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.architexa.diagrams.relo.jdt.actions.OpenReloSessionTreeDialog.java

Source

/* 
 * Copyright (c) 2004-2005 Massachusetts Institute of Technology. This code was
 * developed as part of the Haystack (http://haystack.lcs.mit.edu/) research 
 * project at MIT. 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. 
 */

/*
 * Created on Aug 26, 2005
 */
package com.architexa.diagrams.relo.jdt.actions;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;

import com.architexa.diagrams.model.DocPath;
import com.architexa.diagrams.relo.ReloPlugin;

public class OpenReloSessionTreeDialog extends Dialog {
    private final TreeNode rootTNode;

    private final LabelProvider lblProvider;
    private StructuredViewer treeViewer;
    private final List<?> navPaths;

    private static class TreeNode {
        public Object node;
        public Object reason; // pointer to creator of this tree node
        public List<TreeNode> children;

        private TreeNode(Object node, Object reason) {
            this.node = node;
            this.reason = reason;
            this.children = null;
        }

        public TreeNode() {
            this.node = null;
            this.children = new ArrayList<TreeNode>(5);
        }

        public TreeNode addTNodeChild(TreeNode childTNode) {
            if (children == null)
                children = new ArrayList<TreeNode>(5);
            children.add(childTNode);
            return childTNode;
        }

        public TreeNode addChild(Object child, Object reason) {
            return addTNodeChild(new TreeNode(child, reason));
        }

        private TreeNode findOrCreateTNode(Map<Object, TreeNode> treeNdxMap, Object node, Object reason) {
            TreeNode parentTNode = this;
            TreeNode retTNode = treeNdxMap.get(node);
            if (retTNode == null) {
                retTNode = parentTNode.addChild(node, reason);
                treeNdxMap.put(node, retTNode);
                //System.err.println("\tAdded: " + dump(parentTNode) + " / " + dump(retTNode));
            }
            return retTNode;
        }

        // difference from above is that when a path exists we don't just switch over to it, because the parent must also match
        // makes sure that this child is a node of this parent, i.e. doesn't matter if it is in the tree in other places as well
        private TreeNode createTNode(Map<Object, TreeNode> treeNdxMap, Object newNode, Object reason) {
            TreeNode parentTNode = this;
            // check for dupes
            if (parentTNode.children != null) {
                for (TreeNode child : parentTNode.children) {
                    if (child.node.equals(newNode)) {
                        treeNdxMap.put(newNode, child);
                        return child;
                    }
                }
            }
            TreeNode retTNode = parentTNode.addChild(newNode, reason);
            treeNdxMap.put(newNode, retTNode);
            //System.err.println("\tAdded: " + dump(parentTNode) + " / " + dump(retTNode));
            return retTNode;
        }
    };

    private final class NavPathsLabelProvider extends JavaElementLabelProvider {
        public NavPathsLabelProvider() {
            super(SHOW_SMALL_ICONS | SHOW_PARAMETERS);
        }

        @Override
        public String getText(Object element) {
            if (element == null)
                return null;
            if (element instanceof TreeNode) {
                TreeNode tn = (TreeNode) element;
                if (tn.node instanceof IJavaElement)
                    return super.getText(tn.node);
            }
            System.err.println("Unexpected element for getText. Type: " + element.getClass());
            if (element instanceof IJavaElement)
                return super.getText(element);
            //return ((IJavaElement)element).getElementName();
            if (element instanceof DocPath) {
                return "-> " + getText(((DocPath) element).src);
            }
            return element.toString();
        }

        @Override
        public Image getImage(Object element) {
            if (element instanceof TreeNode) {
                TreeNode tn = (TreeNode) element;
                if (tn.node instanceof IJavaElement)
                    return super.getImage(tn.node);
            }
            System.err.println("Unexpected element for getImage. Type: " + element.getClass());
            if (element instanceof IJavaElement)
                return super.getImage(element);
            else if (element instanceof DocPath)
                return super.getImage(((DocPath) element).dst);
            return null;
        }
    }

    private class TreeContentProvider implements ITreeContentProvider {

        public Object[] getElements(Object inputElement) {
            return rootTNode.children.toArray();
        }

        public Object[] getChildren(Object parentElement) {
            if (hasChildren(parentElement))
                return ((TreeNode) parentElement).children.toArray();
            else
                return new Object[] {};
        }

        public boolean hasChildren(Object parentElement) {
            if (((TreeNode) parentElement).children == null)
                return false;
            else
                return true;
        }

        public Object getParent(Object element) {
            return null;
        }

        public void dispose() {
        }

        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
        }
    };

    // this is just a method for debugging (hence suppressing unused)
    @SuppressWarnings("unused")
    private static String dump(Object node) {
        if (node == null) {
            return "{null}";
        } else if (node instanceof IJavaElement) {
            return ((IJavaElement) node).getElementName();
        } else if (node instanceof DocPath) {
            DocPath dp = (DocPath) node;
            return dump(dp.src) + " --> " + dump(dp.dst);
        } else if (node instanceof TreeNode) {
            TreeNode tn = (TreeNode) node;
            if (tn.children != null)
                return dump(tn.node) + "[" + tn.children.size() + "]";
            else
                return dump(tn.node) + "[]";
        } else
            return node.toString();
    }

    public OpenReloSessionTreeDialog(Shell shell, List<?> navPaths) {
        super(shell);
        this.navPaths = navPaths;
        TreeNode convertedRootTNode = convertPathsToTree(navPaths);
        this.rootTNode = addProjectTNode(convertedRootTNode);
        this.lblProvider = new NavPathsLabelProvider();
    }

    private static TreeNode convertPathsToTree(List<?> navPaths) {
        TreeNode rootTNode = new TreeNode();
        TreeNode prevParentTNode = rootTNode;
        Map<Object, TreeNode> treeNdxMap = new HashMap<Object, TreeNode>();
        for (Object node : navPaths) {
            TreeNode tNode;

            //System.err.println("processing: " + dump(node));

            if (node instanceof DocPath) {
                DocPath dp = (DocPath) node;
                TreeNode srcTNode = prevParentTNode.findOrCreateTNode(treeNdxMap, dp.src, node);
                tNode = srcTNode.createTNode(treeNdxMap, dp.dst, node);

                prevParentTNode = tNode;
            } else {
                tNode = prevParentTNode.findOrCreateTNode(treeNdxMap, node, node);

                //prevParentTNode = tNode;
            }
        }
        return rootTNode;
    }

    private static TreeNode addProjectTNode(TreeNode rootTNode) {
        TreeNode newRootTNode = new TreeNode();

        Map<IJavaProject, TreeNode> projTNodeMap = new HashMap<IJavaProject, TreeNode>();
        for (TreeNode topChildTNode : rootTNode.children) {
            if (!(topChildTNode.node instanceof IJavaElement))
                continue;
            IJavaProject curProj = ((IJavaElement) topChildTNode.node).getJavaProject();
            TreeNode curProjTNode = projTNodeMap.get(curProj);
            if (curProjTNode == null) {
                curProjTNode = newRootTNode.addChild(curProj, curProj);
                projTNodeMap.put(curProj, curProjTNode);
            }
            curProjTNode.addTNodeChild(topChildTNode);
        }
        return newRootTNode;
    }

    @Override
    protected void configureShell(Shell newShell) {
        super.configureShell(newShell);
        newShell.setText("Select Paths");
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        Composite dlgComposite = (Composite) super.createDialogArea(parent);

        Composite composite = new Composite(dlgComposite, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));

        Label lbl = new Label(composite, SWT.NO_FOCUS);
        lbl.setText("Select path to open in Relo Session:");

        ToolBar imgTB = new ToolBar(composite, SWT.FLAT | SWT.HORIZONTAL);
        ToolItem imgToolItem = new ToolItem(imgTB, SWT.PUSH);
        try {
            URL url = ReloPlugin.getDefault().getBundle().getEntry("icons/remove.gif");
            imgToolItem.setImage(new Image(Display.getDefault(), url.openStream()));
        } catch (IOException e) {
            imgToolItem.setText("x");
        }
        imgToolItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent event) {
                removeSelected();
            }
        });
        imgTB.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));

        treeViewer = new TreeViewer(composite, SWT.BORDER);
        GridData treeGridData = new GridData(GridData.FILL_BOTH);
        treeGridData.minimumWidth = convertHorizontalDLUsToPixels(3 * IDialogConstants.BUTTON_WIDTH);
        treeGridData.minimumHeight = convertVerticalDLUsToPixels(4 * IDialogConstants.BUTTON_BAR_HEIGHT);
        treeGridData.horizontalSpan = 2;
        treeViewer.getControl().setLayoutData(treeGridData);
        treeViewer.setContentProvider(new TreeContentProvider());
        treeViewer.setLabelProvider(lblProvider);
        treeViewer.setInput(rootTNode);

        treeViewer.getControl().setFocus();

        //viewer.setSelection(new StructuredSelection(navPaths[0]));
        return dlgComposite;
    }

    /**
     * Removes selected imtes from the tree view (called when the 'x' button is
     * clicked
     */
    private void removeSelected() {
        TreeItem[] selItems = ((Tree) treeViewer.getControl()).getSelection();
        for (TreeItem selItem : selItems) {
            TreeItem parentTItem = selItem.getParentItem();
            TreeNode parentTNode = null;
            if (parentTItem == null)
                parentTNode = rootTNode;
            else
                parentTNode = (TreeNode) parentTItem.getData();
            TreeNode selTNode = (TreeNode) selItem.getData();
            parentTNode.children.remove(selTNode);
            if (selTNode.reason instanceof IJavaProject) {
                for (TreeNode projChildrenTNodes : selTNode.children) {
                    navPaths.remove(projChildrenTNodes.reason);
                }
            } else {
                navPaths.remove(selTNode.reason);
            }
        }
        treeViewer.refresh();
    }
}