com.aptana.ide.installer.wizard.PluginsTreeViewer.java Source code

Java tutorial

Introduction

Here is the source code for com.aptana.ide.installer.wizard.PluginsTreeViewer.java

Source

/**
 * This file Copyright (c) 2005-2010 Aptana, Inc. This program is
 * dual-licensed under both the Aptana Public License and the GNU General
 * Public license. You may elect to use one or the other of these licenses.
 * 
 * This program is distributed in the hope that it will be useful, but
 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
 * NONINFRINGEMENT. Redistribution, except as permitted by whichever of
 * the GPL or APL you select, is prohibited.
 *
 * 1. For the GPL license (GPL), you can redistribute and/or modify this
 * program under the terms of the GNU General Public License,
 * Version 3, as published by the Free Software Foundation.  You should
 * have received a copy of the GNU General Public License, Version 3 along
 * with this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 * 
 * Aptana provides a special exception to allow redistribution of this file
 * with certain Eclipse Public Licensed code and certain additional terms
 * pursuant to Section 7 of the GPL. You may view the exception and these
 * terms on the web at http://www.aptana.com/legal/gpl/.
 * 
 * 2. For the Aptana Public License (APL), this program and the
 * accompanying materials are made available under the terms of the APL
 * v1.0 which accompanies this distribution, and is available at
 * http://www.aptana.com/legal/apl/.
 * 
 * You may view the GPL, Aptana's exception and additional terms, and the
 * APL in the file titled license.html at the root of the corresponding
 * plugin containing this source file.
 * 
 * Any modifications to this file must keep this entire header intact.
 */
package com.aptana.ide.installer.wizard;

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

import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ITreeViewerListener;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeExpansionEvent;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer;

import com.aptana.ide.core.ui.update.PluginsImageRegistry;
import com.aptana.ide.update.manager.InstallerCategory;
import com.aptana.ide.update.manager.Plugin;

/**
 * @author Michael Xia (mxia@aptana.com)
 */
public class PluginsTreeViewer implements ICheckStateListener {

    public static interface Listener {
        public void itemsChecked(int count);
    }

    private static final Color FOREGROUND_INSTALLED = Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
    private static final Color FOREGROUND_REGULAR = Display.getDefault().getSystemColor(SWT.COLOR_LIST_FOREGROUND);

    /**
     * The content provider for the plugin tree viewer.
     */
    private static class ContentProvider implements ITreeContentProvider {

        public Object[] getChildren(Object parentElement) {
            if (parentElement instanceof PluginsTreeModel) {
                // the first level of the tree contains all the plugins with
                // category "Platforms" and all the other categories
                PluginsTreeModel model = (PluginsTreeModel) parentElement;
                return model.getCategories();
            }
            if (parentElement instanceof PluginTreeNode) {
                PluginTreeNode node = (PluginTreeNode) parentElement;
                return node.getChildren();
            }
            return null;
        }

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

        public boolean hasChildren(Object element) {
            return getChildren(element).length > 0;
        }

        public Object[] getElements(Object inputElement) {
            return getChildren(inputElement);
        }

        public void dispose() {
        }

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

    }

    /**
     * The label provider for the plugin tree viewer.
     */
    private class LabelProvider implements ITableLabelProvider {

        public Image getColumnImage(Object element, int columnIndex) {
            switch (columnIndex) {
            case 0:
                Image image = null;
                if (element instanceof PluginTreeNode) {
                    Plugin plugin = getPlugin((PluginTreeNode) element);
                    if (plugin != null) {
                        image = fImages.getImage((Plugin) plugin);
                    }
                }
                return image == null ? PluginsImageRegistry.getDefaultImage() : image;
            }
            return null;
        }

        public String getColumnText(Object element, int columnIndex) {
            switch (columnIndex) {
            case 0:
                if (element instanceof PluginTreeNode) {
                    PluginTreeNode node = (PluginTreeNode) element;
                    Object data = node.getData();
                    if (data == null) {
                        return node.getID();
                    }
                    String name = data.toString();
                    if (node.isInstalled()) {
                        return name + " (installed)"; //$NON-NLS-1$
                    }
                    return name;
                }
                break;
            case 1:
                if (element instanceof PluginTreeNode) {
                    Plugin plugin = getPlugin((PluginTreeNode) element);
                    if (plugin != null) {
                        String description = plugin.getDescription();
                        if (description != null) {
                            return description;
                        }
                    }
                }
                break;
            }
            return null;
        }

        public void addListener(ILabelProviderListener listener) {
        }

        public void dispose() {
        }

        public boolean isLabelProperty(Object element, String property) {
            return false;
        }

        public void removeListener(ILabelProviderListener listener) {
        }

    }

    /*
     * Returns the Plugin instance attached to the given node. 
     * 
     * @param node A PluginTreeNode
     * @return The Plugin, or <code>null</code> in case that the node data does not hold a Plugin
     */
    private Plugin getPlugin(PluginTreeNode node) {
        Object data = node.getData();
        if (data != null && data instanceof Plugin) {
            return (Plugin) data;
        }
        return null;
    }

    private class PluginsComparator extends ViewerComparator {

        public int category(Object element) {
            if (element instanceof PluginTreeNode) {
                PluginTreeNode node = (PluginTreeNode) element;
                Object plugin = node.getData();
                if (plugin != null) {
                    if (plugin instanceof InstallerCategory) {
                        return ((InstallerCategory) plugin).getSortWeight();
                    }
                    if (plugin instanceof Plugin) {
                        return ((Plugin) plugin).getSortweight();
                    }
                }
            }
            return super.category(element);
        }

    }

    private ContainerCheckedTreeViewer fTreeViewer;
    private PluginsTreeModel fModel;
    private Object[] fCheckedElements;
    private PluginsImageRegistry fImages;
    private List<Listener> fListeners;

    public PluginsTreeViewer(Composite parent) {
        fImages = new PluginsImageRegistry(parent.getDisplay());
        fCheckedElements = new Object[0];
        fListeners = new ArrayList<Listener>();
        createContents(parent);
    }

    public void addListener(Listener listener) {
        fListeners.add(listener);
    }

    public void removeListener(Listener listener) {
        fListeners.remove(listener);
    }

    /**
     * Disposes the viewer.
     */
    public void dispose() {
        fModel.clear();
        fListeners.clear();
    }

    /**
     * Returns the main control of the viewer
     * 
     * @return the main control
     */
    public Control getControl() {
        return fTreeViewer.getControl();
    }

    /**
     * Returns the list of plug-ins user selected to install.
     * 
     * @return an array of plug-ins to install
     */
    public Plugin[] getSelectedPlugins() {
        List<Plugin> plugins = new ArrayList<Plugin>();
        Object[] elements = fTreeViewer.getCheckedElements();
        PluginTreeNode node;
        for (Object element : elements) {
            if (element instanceof PluginTreeNode) {
                node = (PluginTreeNode) element;
                // filters out the ones that either are already installed or do
                // not correspond to a plug-in node
                if (!node.isInstalled() && node.getData() instanceof Plugin) {
                    plugins.add((Plugin) node.getData());
                }
            }
        }
        return plugins.toArray(new Plugin[plugins.size()]);
    }

    /**
     * Makes the specific categories expanded.
     * 
     * @param categoryIDs the array of category ids
     */
    public void setExpandedCategories(String[] categoryIDs) {
        if (categoryIDs == null || categoryIDs.length == 0) {
            return;
        }
        // finds the categories that need to be expanded
        List<PluginTreeNode> categories = new ArrayList<PluginTreeNode>();
        PluginTreeNode category;
        for (String id : categoryIDs) {
            category = fModel.getCategory(id);
            if (category != null) {
                categories.add(category);
            }
        }
        fTreeViewer.setExpandedElements(categories.toArray(new PluginTreeNode[categories.size()]));
        if (categories.size() > 0) {
            // auto-selects the first element
            fTreeViewer.setSelection(new StructuredSelection(categories.get(0)));
        }
    }

    /**
     * @see org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged(org.eclipse.jface.viewers.CheckStateChangedEvent)
     */
    public void checkStateChanged(CheckStateChangedEvent event) {
        Object element = event.getElement();
        if (element instanceof PluginTreeNode) {
            PluginTreeNode node = (PluginTreeNode) element;
            if (node.isInstalled() || hasInstalledChildren(node)) {
                // disables checking of the box for installed plug-ins and any
                // node that contains them
                fTreeViewer.setCheckedElements(fCheckedElements);
            } else {
                // stores only the list of non-grayed, checked elements
                List<Object> checked = new ArrayList<Object>();
                Object[] elements = fTreeViewer.getCheckedElements();
                for (Object checkedElement : elements) {
                    if (!fTreeViewer.getGrayed(checkedElement)) {
                        checked.add(checkedElement);
                    }
                }
                fCheckedElements = checked.toArray(new Object[checked.size()]);
                fireItemsCheckedEvent();
            }
        }
    }

    private void createContents(Composite parent) {
        fTreeViewer = new ContainerCheckedTreeViewer(parent,
                SWT.SINGLE | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
        Tree tree = fTreeViewer.getTree();
        tree.setHeaderVisible(true);
        fTreeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);

        TreeColumn column = new TreeColumn(tree, SWT.LEFT);
        column.setText("Plugin"); //$NON-NLS-1$
        column.setWidth(350);

        column = new TreeColumn(tree, SWT.LEFT);
        column.setText("Description"); //$NON-NLS-1$
        column.setWidth(350);

        fTreeViewer.setContentProvider(new ContentProvider());
        fTreeViewer.setLabelProvider(new LabelProvider());
        fTreeViewer.setComparator(new PluginsComparator());
        fTreeViewer.setInput(fModel = new PluginsTreeModel());
        fTreeViewer.addCheckStateListener(this);
        fTreeViewer.addTreeListener(new ITreeViewerListener() {

            public void treeCollapsed(TreeExpansionEvent event) {
                updateForeground();
            }

            public void treeExpanded(TreeExpansionEvent event) {
                updateForeground();
            }

        });

        updateExpansionState();
        updateForeground();
    }

    private void updateExpansionState() {
        fTreeViewer.setExpandedElements(fModel.getExpandedCategories());
    }

    private void updateForeground() {
        // SWT currently does not have an API to disable individual TreeItem, so
        // have to modify the appearance manually
        List<TreeItem> items = new ArrayList<TreeItem>();
        getAllVisibleItems(items, fTreeViewer.getTree().getItems());
        Object data;
        PluginTreeNode node;
        for (TreeItem item : items) {
            data = item.getData();
            if (data != null && data instanceof PluginTreeNode) {
                node = (PluginTreeNode) data;
                if (node.isInstalled()) {
                    item.setForeground(FOREGROUND_INSTALLED);
                } else {
                    item.setForeground(FOREGROUND_REGULAR);
                }
            }
        }
    }

    private void fireItemsCheckedEvent() {
        int count = fCheckedElements.length;
        for (Listener listener : fListeners) {
            listener.itemsChecked(count);
        }
    }

    private static void getAllVisibleItems(List<TreeItem> items, TreeItem[] topLevelItems) {
        for (TreeItem item : topLevelItems) {
            items.add(item);
            getAllVisibleItems(items, item.getItems());
        }
    }

    private static boolean hasInstalledChildren(PluginTreeNode node) {
        PluginTreeNode[] children = node.getChildren();
        for (PluginTreeNode child : children) {
            if (child.isInstalled() || hasInstalledChildren(child)) {
                return true;
            }
        }
        return false;
    }

}