org.eclipse.mylyn.internal.tasks.ui.views.TaskListRefreshJob.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.mylyn.internal.tasks.ui.views.TaskListRefreshJob.java

Source

/*******************************************************************************
 * Copyright (c) 2013 Tasktop Technologies 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:
 *     Tasktop Technologies - initial API and implementation
 *******************************************************************************/

package org.eclipse.mylyn.internal.tasks.ui.views;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.commons.workbench.DelayedRefreshJob;
import org.eclipse.mylyn.internal.tasks.core.AbstractTask;
import org.eclipse.mylyn.internal.tasks.core.AbstractTaskContainer;
import org.eclipse.mylyn.internal.tasks.core.ITaskListChangeListener;
import org.eclipse.mylyn.internal.tasks.core.TaskContainerDelta;
import org.eclipse.mylyn.internal.tasks.core.UncategorizedTaskContainer;
import org.eclipse.mylyn.internal.tasks.core.UnmatchedTaskContainer;
import org.eclipse.mylyn.internal.tasks.core.UnsubmittedTaskContainer;
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
import org.eclipse.mylyn.internal.tasks.ui.editors.TaskListChangeAdapter;
import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal;
import org.eclipse.mylyn.internal.tasks.ui.util.TreeWalker;
import org.eclipse.mylyn.internal.tasks.ui.util.TreeWalker.TreeVisitor;
import org.eclipse.mylyn.tasks.core.ITaskContainer;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.PlatformUI;

public final class TaskListRefreshJob extends DelayedRefreshJob {
    private final AbstractTaskListView taskListView;

    private final ITaskListChangeListener TASKLIST_CHANGE_LISTENER = new TaskListChangeAdapter() {

        @Override
        public void containersChanged(final Set<TaskContainerDelta> deltas) {
            PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
                public void run() {
                    for (TaskContainerDelta taskContainerDelta : deltas) {
                        if (taskListView.isScheduledPresentation()) {
                            // TODO: implement refresh policy for scheduled presentation
                            refresh();
                        } else {
                            switch (taskContainerDelta.getKind()) {
                            case ROOT:
                                refresh();
                                break;
                            case ADDED:
                            case REMOVED:
                                if (isFilteredContainer(taskContainerDelta)) {
                                    // container may have changed visibility, refresh root
                                    refresh();
                                } else {
                                    if (taskContainerDelta.getElement() != null) {
                                        refreshElement(taskContainerDelta.getElement());
                                    }
                                    if (taskContainerDelta.getParent() != null) {
                                        refreshElement(taskContainerDelta.getParent());
                                    } else {
                                        // element was added/removed from the root
                                        refresh();
                                    }
                                }
                                break;
                            case CONTENT:
                                refreshElement(taskContainerDelta.getElement());
                            }

                        }
                    }
                }

                private boolean isFilteredContainer(TaskContainerDelta taskContainerDelta) {
                    ITaskContainer parent = taskContainerDelta.getParent();
                    return parent instanceof UnsubmittedTaskContainer || parent instanceof UnmatchedTaskContainer
                            || parent instanceof UncategorizedTaskContainer;
                }
            });
        }
    };

    public TaskListRefreshJob(AbstractTaskListView taskListView, TreeViewer treeViewer, String name) {
        super(treeViewer, name);
        this.taskListView = taskListView;
        TasksUiInternal.getTaskList().addChangeListener(TASKLIST_CHANGE_LISTENER);
    }

    @Override
    protected void doRefresh(Object[] items) {
        TreePath selection = preserveSelection();

        if (items == null) {
            viewer.refresh(true);
        } else if (items.length > 0) {
            try {
                if (taskListView.isFocusedMode()) {
                    Set<Object> children = new HashSet<Object>(Arrays.asList(items));
                    Set<AbstractTaskContainer> parents = new HashSet<AbstractTaskContainer>();
                    for (Object item : items) {
                        if (item instanceof AbstractTask) {
                            parents.addAll(((AbstractTask) item).getParentContainers());
                        }
                    }
                    // 1. refresh parents
                    children.removeAll(parents);
                    for (AbstractTaskContainer parent : parents) {
                        viewer.refresh(parent, false);
                        // only refresh label of parent
                        viewer.update(parent, null);
                    }
                    // 2. refresh children
                    for (Object item : children) {
                        viewer.refresh(item, true);
                    }
                    // 3. update states of all changed items
                    for (Object item : items) {
                        updateExpansionState(item);
                    }
                } else {
                    Set<AbstractTaskContainer> parents = new HashSet<AbstractTaskContainer>();
                    for (Object item : items) {
                        if (item instanceof AbstractTask) {
                            parents.addAll(((AbstractTask) item).getParentContainers());
                        }
                        viewer.refresh(item, true);
                        updateExpansionState(item);
                    }
                    // refresh labels of parents for task activation or incoming indicators
                    for (AbstractTaskContainer parent : parents) {
                        // only refresh label
                        viewer.update(parent, null);
                    }
                }
            } catch (SWTException e) {
                StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, "Failed to refresh viewer: " //$NON-NLS-1$
                        + viewer, e));
            }
        }

        taskListView.updateToolTip(false);
        restoreSelection(selection);
    }

    private TreePath preserveSelection() {
        if (viewer instanceof TreeViewer) {
            TreeViewer treeViewer = (TreeViewer) viewer;
            // in case the refresh removes the currently selected item, 
            // remember the next item in the tree to restore the selection
            // TODO: consider making this optional
            TreeItem[] selection = treeViewer.getTree().getSelection();
            if (selection.length > 0) {
                TreeWalker treeWalker = new TreeWalker(treeViewer);
                return treeWalker.walk(new TreeVisitor() {
                    @Override
                    public boolean visit(Object object) {
                        return true;
                    }
                }, selection[selection.length - 1]);
            }
        }
        return null;
    }

    private void restoreSelection(TreePath treePath) {
        if (treePath != null) {
            ISelection newSelection = viewer.getSelection();
            if (newSelection == null || newSelection.isEmpty()) {
                viewer.setSelection(new TreeSelection(treePath), true);
            }
        }
    }

    protected void updateExpansionState(Object item) {
        if (taskListView.isFocusedMode() && taskListView.isAutoExpandMode()) {
            taskListView.getViewer().expandToLevel(item, 3);
        }
    }

    public void dispose() {
        TasksUiInternal.getTaskList().removeChangeListener(TASKLIST_CHANGE_LISTENER);
    }
}