blob: 741109009228ffe5c2b8bad731bda8081960eb97 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2013 Tasktop Technologies and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*
* Tasktop Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.internal.team.ui.history;
import java.lang.reflect.InvocationTargetException;
import java.text.DateFormat;
import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.CompareEditorInput;
import org.eclipse.compare.CompareUI;
import org.eclipse.compare.structuremergeviewer.Differencer;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.mylyn.commons.ui.AbstractColumnViewerSupport;
import org.eclipse.mylyn.internal.tasks.core.sync.GetTaskHistoryJob;
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
import org.eclipse.mylyn.internal.tasks.ui.compare.TaskDataDiffNode;
import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal;
import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector;
import org.eclipse.mylyn.tasks.core.ITask;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.core.data.TaskData;
import org.eclipse.mylyn.tasks.core.data.TaskHistory;
import org.eclipse.mylyn.tasks.core.data.TaskRevision;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
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.team.ui.history.HistoryPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
/**
* @author Steffen Pingel
*/
public class TaskHistoryPage extends HistoryPage {
private class AddedLabelProvider extends ChangeLabelProvider {
@Override
public String getText(TaskRevision.Change change) {
return change.getAdded();
}
}
private static class AuthorLabelProvider extends ColumnLabelProvider {
@Override
public String getText(Object element) {
if (element instanceof TaskRevision) {
TaskRevision entry = (TaskRevision) element;
return entry.getAuthor().toString();
} else if (element instanceof TaskRevision.Change) {
return null;
}
return super.getText(element);
}
}
private static abstract class ChangeLabelProvider extends ColumnLabelProvider {
@Override
public String getText(Object element) {
if (element instanceof TaskRevision) {
TaskRevision entry = (TaskRevision) element;
if (entry.getChanges().size() == 1) {
return getText(entry.getChanges().get(0));
}
return null;
} else if (element instanceof TaskRevision.Change) {
return getText((TaskRevision.Change) element);
}
return super.getText(element);
}
public abstract String getText(TaskRevision.Change change);
}
private class FieldLabelProvider extends ChangeLabelProvider {
@Override
public String getText(TaskRevision.Change change) {
return change.getField();
}
}
private class RemovedLabelProvider extends ChangeLabelProvider {
@Override
public String getText(TaskRevision.Change change) {
return change.getRemoved();
}
}
private static class TimeLabelProvider extends ColumnLabelProvider {
private final DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT);
@Override
public String getText(Object element) {
if (element instanceof TaskRevision) {
TaskRevision entry = (TaskRevision) element;
return (entry.getDate() != null) ? formatter.format(entry.getDate()) : null;
} else if (element instanceof TaskRevision.Change) {
return null;
}
return super.getText(element);
}
}
public static boolean canShowHistoryFor(Object object) {
ITask task = getTask(object);
if (task != null) {
AbstractRepositoryConnector connector = TasksUiPlugin.getRepositoryManager().getRepositoryConnector(
task.getConnectorKind());
TaskRepository repository = TasksUiPlugin.getRepositoryManager().getRepository(task.getConnectorKind(),
task.getRepositoryUrl());
return connector.canGetTaskHistory(repository, task);
}
return false;
}
public static ITask getTask(Object object) {
ITask task = null;
if (object instanceof ITask) {
task = (ITask) object;
} else if (object instanceof IAdaptable) {
task = (ITask) ((IAdaptable) object).getAdapter(ITask.class);
}
return task;
}
private TaskHistoryContentProvider contentProvider;
private GetTaskHistoryJob refreshOperation;
private TreeViewer viewer;
public TaskHistoryPage() {
}
@Override
public void createControl(Composite parent) {
viewer = new TreeViewer(parent, SWT.FULL_SELECTION);
Tree tree = viewer.getTree();
tree.setHeaderVisible(true);
TreeViewerColumn authorViewerColumn = new TreeViewerColumn(viewer, SWT.LEFT);
authorViewerColumn.setLabelProvider(new AuthorLabelProvider());
TreeColumn authorColumn = authorViewerColumn.getColumn();
authorColumn.setText(Messages.TaskHistoryPage_Author_Column_Label);
authorColumn.setWidth(120);
authorColumn.setData(AbstractColumnViewerSupport.KEY_COLUMN_CAN_HIDE, false);
TreeViewerColumn timeViewerColumn = new TreeViewerColumn(viewer, SWT.LEFT);
timeViewerColumn.setLabelProvider(new TimeLabelProvider());
TreeColumn timeColumn = timeViewerColumn.getColumn();
timeColumn.setText(Messages.TaskHistoryPage_Time_Column_Label);
timeColumn.setWidth(140);
TreeViewerColumn fieldViewerColumn = new TreeViewerColumn(viewer, SWT.LEFT);
fieldViewerColumn.setLabelProvider(new FieldLabelProvider());
TreeColumn fieldColumn = fieldViewerColumn.getColumn();
fieldColumn.setText(Messages.TaskHistoryPage_Field_Column_Label);
fieldColumn.setWidth(120);
TreeViewerColumn removedViewerColumn = new TreeViewerColumn(viewer, SWT.LEFT);
removedViewerColumn.setLabelProvider(new RemovedLabelProvider());
TreeColumn remmovedColumn = removedViewerColumn.getColumn();
remmovedColumn.setText(Messages.TaskHistoryPage_Removed_Column_Label);
remmovedColumn.setWidth(120);
TreeViewerColumn addedViewerColumn = new TreeViewerColumn(viewer, SWT.LEFT);
addedViewerColumn.setLabelProvider(new AddedLabelProvider());
TreeColumn addedColumn = addedViewerColumn.getColumn();
addedColumn.setText(Messages.TaskHistoryPage_Added_Column_Label);
addedColumn.setWidth(120);
contentProvider = new TaskHistoryContentProvider();
viewer.setContentProvider(contentProvider);
viewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
Object item = ((IStructuredSelection) event.getSelection()).getFirstElement();
if (item instanceof TaskRevision) {
final TaskRevision revision = (TaskRevision) item;
final TaskHistory history = (TaskHistory) viewer.getInput();
CompareConfiguration configuration = new CompareConfiguration();
configuration.setProperty(CompareConfiguration.IGNORE_WHITESPACE, Boolean.valueOf(true));
configuration.setLeftEditable(false);
configuration.setLeftLabel(Messages.TaskHistoryPage_Old_Value_Label);
configuration.setRightEditable(false);
configuration.setRightLabel(Messages.TaskHistoryPage_New_Value_Label);
CompareEditorInput editorInput = new CompareEditorInput(configuration) {
@Override
protected Object prepareInput(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
try {
AbstractRepositoryConnector connector = TasksUiPlugin.getRepositoryManager()
.getRepositoryConnector(history.getTask().getConnectorKind());
TaskData newData = connector.getTaskData(history.getRepository(), history.getTask()
.getTaskId(), monitor);
TaskData oldData = TasksUiInternal.computeTaskData(newData, history, revision.getId(),
monitor);
return new TaskDataDiffNode(Differencer.CHANGE, oldData, newData);
} catch (CoreException e) {
throw new InvocationTargetException(e);
}
}
};
CompareUI.openCompareEditor(editorInput);
}
}
});
}
@Override
public void dispose() {
cancelRefresh();
super.dispose();
}
public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
return null;
}
@Override
public Control getControl() {
return viewer.getControl();
}
public String getDescription() {
return NLS.bind(Messages.TaskHistoryPage_Task_history_for_X_Desscription_Label, getName());
}
public String getName() {
ITask task = getTask();
return (task != null) ? task.getSummary() : null;
}
public ITask getTask() {
return getTask(getInput());
}
@Override
public boolean inputSet() {
cancelRefresh();
if (viewer == null) {
return false;
}
final ITask task = getTask();
if (task != null) {
AbstractRepositoryConnector connector = TasksUiPlugin.getRepositoryManager().getRepositoryConnector(
task.getConnectorKind());
TaskRepository repository = TasksUiPlugin.getRepositoryManager().getRepository(task.getConnectorKind(),
task.getRepositoryUrl());
refreshOperation = new GetTaskHistoryJob(connector, repository, task);
refreshOperation.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(final IJobChangeEvent event) {
if (!event.getResult().isOK()) {
return;
}
if (Display.getDefault().isDisposed()) {
return;
}
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (viewer.getControl() != null && !viewer.getControl().isDisposed()) {
TaskHistory history = ((GetTaskHistoryJob) event.getJob()).getHistory();
viewer.setInput(history);
}
}
});
}
});
schedule(refreshOperation);
return true;
}
return false;
}
public boolean isValidInput(Object object) {
return canShowHistoryFor(object);
}
public void refresh() {
inputSet();
}
@Override
public void setFocus() {
if (viewer != null) {
viewer.getControl().setFocus();
}
}
private void cancelRefresh() {
if (refreshOperation != null) {
refreshOperation.cancel();
refreshOperation = null;
}
}
private IWorkbenchPartSite getWorkbenchSite() {
final IWorkbenchPart part = getHistoryPageSite().getPart();
return part != null ? part.getSite() : null;
}
private void schedule(final Job job) {
final IWorkbenchPartSite site = getWorkbenchSite();
if (site != null) {
IWorkbenchSiteProgressService progress = (IWorkbenchSiteProgressService) site.getAdapter(IWorkbenchSiteProgressService.class);
if (progress != null) {
progress.schedule(job, 0, true);
return;
}
}
// fall-back
job.schedule();
}
}