eu.esdihumboldt.hale.ui.views.tasks.TaskTreeView.java Source code

Java tutorial

Introduction

Here is the source code for eu.esdihumboldt.hale.ui.views.tasks.TaskTreeView.java

Source

/*
 * Copyright (c) 2012 Data Harmonisation Panel
 * 
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution. If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors:
 *     HUMBOLDT EU Integrated Project #030962
 *     Data Harmonisation Panel <http://www.dhpanel.eu>
 */
package eu.esdihumboldt.hale.ui.views.tasks;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.layout.TreeColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IColorProvider;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeColumnViewerLabelProvider;
import org.eclipse.jface.viewers.TreeNode;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.part.WorkbenchPart;

import eu.esdihumboldt.hale.schemaprovider.model.SchemaElement;
import eu.esdihumboldt.hale.ui.service.HaleServiceListener;
import eu.esdihumboldt.hale.ui.service.schema.SchemaService;
import eu.esdihumboldt.hale.ui.util.tree.CollectionTreeNodeContentProvider;
import eu.esdihumboldt.hale.ui.util.tree.DefaultTreeNode;
import eu.esdihumboldt.hale.ui.util.tree.MapTreeNode;
import eu.esdihumboldt.hale.ui.util.tree.SortedMapTreeNode;
import eu.esdihumboldt.hale.ui.views.schemas.ModelNavigationView;
import eu.esdihumboldt.hale.ui.views.tasks.internal.Messages;
import eu.esdihumboldt.hale.ui.views.tasks.model.ResolvedTask;
import eu.esdihumboldt.hale.ui.views.tasks.model.Task;
import eu.esdihumboldt.hale.ui.views.tasks.model.TaskUtils;
import eu.esdihumboldt.hale.ui.views.tasks.service.TaskService;
import eu.esdihumboldt.hale.ui.views.tasks.service.TaskServiceAdapter;

/**
 * Task view based on a tree
 * 
 * @author Simon Templer
 * @partner 01 / Fraunhofer Institute for Computer Graphics Research
 */
public class TaskTreeView extends ViewPart {

    /**
     * The view ID
     */
    public static String ID = "eu.esdihumboldt.hale.ui.views.tasks"; //$NON-NLS-1$

    /**
     * The tree viewer
     */
    private TreeViewer tree;

    private TaskService taskService;

    private HaleServiceListener taskListener;

    private SchemaService schemaService;

    private MapTreeNode<SchemaElement, MapTreeNode<ResolvedTask, TreeNode>> sourceNode;

    private MapTreeNode<SchemaElement, MapTreeNode<ResolvedTask, TreeNode>> targetNode;

    private final Map<Task, DefaultTreeNode> taskNodes = new HashMap<Task, DefaultTreeNode>();

    /**
     * @see WorkbenchPart#createPartControl(Composite)
     */
    @Override
    public void createPartControl(Composite parent) {
        Composite page = new Composite(parent, SWT.NONE);
        GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
        page.setLayoutData(data);

        // tree column layout
        TreeColumnLayout layout = new TreeColumnLayout();
        page.setLayout(layout);

        // tree viewer
        tree = new TreeViewer(page, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER);
        tree.setContentProvider(new CollectionTreeNodeContentProvider());
        tree.setUseHashlookup(true);

        tree.getTree().setHeaderVisible(true);
        tree.getTree().setLinesVisible(true);

        tree.setComparator(new TaskTreeComparator());

        schemaService = (SchemaService) PlatformUI.getWorkbench().getService(SchemaService.class);
        taskService = (TaskService) PlatformUI.getWorkbench().getService(TaskService.class);

        // columns
        IColorProvider colorProvider = new TaskColorProvider(Display.getCurrent());

        // title/description
        TreeViewerColumn description = new TreeViewerColumn(tree, SWT.LEFT);
        description.getColumn().setText(Messages.TaskTreeView_TitleDescriptionText);
        description.getColumn().setToolTipText(Messages.TaskTreeView_description_tooltip);
        TreeColumnViewerLabelProvider descriptionLabelProvider = new TreeColumnViewerLabelProvider(
                new TaskDescriptionLabelProvider(0));
        descriptionLabelProvider.setProviders(colorProvider);
        description.setLabelProvider(descriptionLabelProvider);
        layout.setColumnData(description.getColumn(), new ColumnWeightData(4));

        // value
        TreeViewerColumn value = new TreeViewerColumn(tree, SWT.CENTER);
        value.getColumn().setText("!"); //$NON-NLS-1$
        value.getColumn().setToolTipText(Messages.TaskTreeView_value_tooltip);
        TreeColumnViewerLabelProvider valueLabelProvider = new TreeColumnViewerLabelProvider(
                new TaskValueLabelProvider(0));
        valueLabelProvider.setProviders(colorProvider);
        value.setLabelProvider(valueLabelProvider);
        layout.setColumnData(value.getColumn(), new ColumnWeightData(0, 20));

        // number of tasks
        TreeViewerColumn number = new TreeViewerColumn(tree, SWT.RIGHT);
        number.getColumn().setText("#"); //$NON-NLS-1$
        number.getColumn().setToolTipText(Messages.TaskTreeView_NumberText);
        TreeColumnViewerLabelProvider numberLabelProvider = new TreeColumnViewerLabelProvider(
                new TaskCountLabelProvider(0));
        numberLabelProvider.setProviders(colorProvider);
        number.setLabelProvider(numberLabelProvider);
        layout.setColumnData(number.getColumn(), new ColumnWeightData(0, 48));

        // user data: status
        TreeViewerColumn status = new TreeViewerColumn(tree, SWT.LEFT);
        status.getColumn().setText(Messages.TaskTreeView_StatusText);
        TreeColumnViewerLabelProvider statusLabelProvider = new TreeColumnViewerLabelProvider(
                new TaskStatusLabelProvider(0));
        statusLabelProvider.setProviders(colorProvider);
        status.setLabelProvider(statusLabelProvider);
        layout.setColumnData(status.getColumn(), new ColumnWeightData(1));
        status.setEditingSupport(new TaskStatusEditingSupport(tree, taskService));

        // user data: comment
        TreeViewerColumn comment = new TreeViewerColumn(tree, SWT.LEFT);
        comment.getColumn().setText(Messages.TaskTreeView_CommentText);
        TreeColumnViewerLabelProvider commentLabelProvider = new TreeColumnViewerLabelProvider(
                new TaskCommentLabelProvider(0));
        commentLabelProvider.setProviders(colorProvider);
        comment.setLabelProvider(commentLabelProvider);
        layout.setColumnData(comment.getColumn(), new ColumnWeightData(4));
        comment.setEditingSupport(new TaskCommentEditingSupport(tree, taskService));

        // listeners
        taskService.addListener(taskListener = new TaskServiceAdapter() {

            @Override
            public void tasksRemoved(final Iterable<Task> tasks) {
                if (Display.getCurrent() != null) {
                    removeTasks(tasks);
                } else {
                    final Display display = PlatformUI.getWorkbench().getDisplay();
                    display.syncExec(new Runnable() {

                        @Override
                        public void run() {
                            removeTasks(tasks);
                        }

                    });
                }
            }

            @Override
            public void tasksAdded(final Iterable<Task> tasks) {
                if (Display.getCurrent() != null) {
                    addTasks(tasks);
                } else {
                    final Display display = PlatformUI.getWorkbench().getDisplay();
                    display.syncExec(new Runnable() {

                        @Override
                        public void run() {
                            addTasks(tasks);
                        }

                    });
                }
            }

            @Override
            public void taskUserDataChanged(final ResolvedTask task) {
                if (Display.getCurrent() != null) {
                    updateNode(task);
                } else {
                    final Display display = PlatformUI.getWorkbench().getDisplay();
                    display.syncExec(new Runnable() {

                        @Override
                        public void run() {
                            updateNode(task);
                        }

                    });
                }
            }

        });

        createInput();

        configureActions();

        // interaction
        tree.addDoubleClickListener(new IDoubleClickListener() {

            @Override
            public void doubleClick(DoubleClickEvent event) {
                ISelection selection = event.getSelection();
                if (!selection.isEmpty() && selection instanceof IStructuredSelection) {
                    Object selected = ((IStructuredSelection) selection).getFirstElement();
                    if (selected instanceof TreeNode) {
                        // determine value
                        Object tmp = ((TreeNode) selected).getValue();
                        Object value;
                        if (tmp.getClass().isArray()) {
                            value = ((Object[]) tmp)[0];
                        } else {
                            value = tmp;
                        }
                        if (value instanceof Task) {
                            // node is task node
                            Task task = (Task) value;
                            onDoubleClick(task.getMainContext().getIdentifier());
                        } else if (value instanceof SchemaElement) {
                            SchemaElement type = (SchemaElement) value;
                            onDoubleClick(type.getIdentifier());
                        }
                    }
                }
            }
        });
    }

    /**
     * React on a double click on an item that represents the given identifier
     * 
     * @param identifier the identifier
     */
    protected void onDoubleClick(String identifier) {
        //FIXME use selection mechanism instead of getting the view (real ugly)
        ModelNavigationView modelView = (ModelNavigationView) PlatformUI.getWorkbench().getActiveWorkbenchWindow()
                .getActivePage().findView(ModelNavigationView.ID);
        if (modelView != null) {
            modelView.selectItem(identifier);
        }
    }

    private void configureActions() {
        IActionBars bars = getViewSite().getActionBars();

        // tool-bar
        //IToolBarManager toolBar = bars.getToolBarManager();
        //toolBar.add(...);

        // menu
        IMenuManager menu = bars.getMenuManager();
        menu.add(new TaskProviderMenu());
    }

    /**
     * Update the view
     */
    private void createInput() {
        TaskService taskService = (TaskService) PlatformUI.getWorkbench().getService(TaskService.class);

        final Collection<TreeNode> input = new ArrayList<TreeNode>();
        sourceNode = new SortedMapTreeNode<SchemaElement, MapTreeNode<ResolvedTask, TreeNode>>(
                Messages.TaskTreeView_SourceNodeTitle);
        targetNode = new SortedMapTreeNode<SchemaElement, MapTreeNode<ResolvedTask, TreeNode>>(
                Messages.TaskTreeView_TargetNodeTitle);
        input.add(sourceNode);
        input.add(targetNode);

        Collection<ResolvedTask> tasks = taskService.getResolvedTasks();
        for (ResolvedTask task : tasks) {
            addTask(task);
        }

        tree.setInput(input);
    }

    /**
     * Add a resolved task
     * 
     * @param task the task to add
     */
    private void addTask(ResolvedTask task) {
        // add task to model
        MapTreeNode<ResolvedTask, TreeNode> parent = getParentNode(task, true);
        if (parent != null) {
            DefaultTreeNode node = new DefaultTreeNode(task);
            parent.addChild(task, node);
            taskNodes.put(task.getTask(), node);
            // update viewer
            tree.refresh(parent, true);
            // update icons
            TreeNode updateNode = parent.getParent();
            while (updateNode != null) {
                tree.update(updateNode, null);
                updateNode = updateNode.getParent();
            }
        }
    }

    /**
     * Adds the given tasks
     * 
     * @param tasks the tasks to add
     */
    protected void removeTasks(Iterable<Task> tasks) {
        //TODO smart refresh
        for (Task task : tasks) {
            removeTask(task);
        }
    }

    /**
     * Remove a task
     * 
     * @param task the task to remove
     */
    @SuppressWarnings("unchecked")
    private void removeTask(Task task) {
        DefaultTreeNode node = taskNodes.get(task);

        if (node != null) {
            // remove task from model
            MapTreeNode<ResolvedTask, TreeNode> parent = (MapTreeNode<ResolvedTask, TreeNode>) node.getParent();
            if (parent != null) {
                parent.removeChildNode(node);
                taskNodes.remove(task);
                // remove empty nodes
                if (!parent.hasChildren()) {
                    MapTreeNode<SchemaElement, MapTreeNode<ResolvedTask, TreeNode>> root = (MapTreeNode<SchemaElement, MapTreeNode<ResolvedTask, TreeNode>>) parent
                            .getParent();
                    root.removeChildNode(parent);
                    tree.refresh(root, true);
                } else {
                    tree.refresh(parent, true);
                    // update icons
                    TreeNode updateNode = parent.getParent();
                    while (updateNode != null) {
                        tree.update(updateNode, null);
                        updateNode = updateNode.getParent();
                    }
                }
            }
        }
    }

    /**
     * Update the node label for the given task
     * 
     * @param task the task
     */
    protected void updateNode(ResolvedTask task) {
        DefaultTreeNode node = taskNodes.get(task.getTask());
        if (node != null) {
            node.setValues(task);
            //refresh parent instead of update node (sorting) - tree.update(node, null);

            // update parent nodes
            TreeNode parent = node.getParent();

            if (parent != null) {
                tree.refresh(parent, true);
                parent = parent.getParent();
            } else {
                tree.update(node, null);
            }

            while (parent != null) {
                tree.update(parent, null);
                parent = parent.getParent();
            }
        }
    }

    /**
     * Get the parent node for the given task
     * 
     * @param task the task
     * @param allowCreate allow creating the node if it does not yet exist
     * 
     * @return the parent node
     */
    private MapTreeNode<ResolvedTask, TreeNode> getParentNode(ResolvedTask task, boolean allowCreate) {
        SchemaElement group = TaskUtils.getGroup(task);
        if (group.getElementName().getNamespaceURI().equals(schemaService.getSourceNameSpace())) {
            // source task
            return getGroupNode(sourceNode, group, allowCreate);
        } else if (group.getElementName().getNamespaceURI().equals(schemaService.getTargetNameSpace())) {
            // target task
            return getGroupNode(targetNode, group, allowCreate);
        } else {
            // invalid task ?
            MapTreeNode<ResolvedTask, TreeNode> result = getGroupNode(sourceNode, group, false);
            if (result == null) {
                result = getGroupNode(targetNode, group, false);
            }
            return result;
        }
    }

    /**
     * Get the group node for the group defined by the given type definition
     * 
     * @param rootNode the root node
     * @param group the group's type definition
     * @param allowCreate allow creating the node if it does not yet exist
     * 
     * @return the group node
     */
    private MapTreeNode<ResolvedTask, TreeNode> getGroupNode(
            MapTreeNode<SchemaElement, MapTreeNode<ResolvedTask, TreeNode>> rootNode, SchemaElement group,
            boolean allowCreate) {
        MapTreeNode<ResolvedTask, TreeNode> groupNode = rootNode.getChild(group);
        if (groupNode == null && allowCreate) {
            groupNode = new SortedMapTreeNode<ResolvedTask, TreeNode>(group);
            rootNode.addChild(group, groupNode);
            // update viewer
            tree.refresh(rootNode, true);
        }
        return groupNode;
    }

    /**
     * Adds the given tasks
     * 
     * @param tasks the tasks to add
     */
    protected void addTasks(Iterable<Task> tasks) {
        //TODO smart refresh
        for (Task task : tasks) {
            addTask(taskService.resolveTask(task));
        }
    }

    /**
     * @see WorkbenchPart#setFocus()
     */
    @Override
    public void setFocus() {
        tree.getControl().setFocus();
    }

    /**
     * @see WorkbenchPart#dispose()
     */
    @Override
    public void dispose() {
        if (taskListener != null) {
            TaskService taskService = (TaskService) PlatformUI.getWorkbench().getService(TaskService.class);
            taskService.removeListener(taskListener);
        }

        super.dispose();
    }

}