blob: 9d7f5ff004a92b857c5782845f47c2174ba9bd16 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2011 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.context.tasks.ui.editors;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.commons.workbench.WorkbenchUtil;
import org.eclipse.mylyn.context.core.AbstractContextListener;
import org.eclipse.mylyn.context.core.AbstractContextStructureBridge;
import org.eclipse.mylyn.context.core.ContextChangeEvent;
import org.eclipse.mylyn.context.core.ContextCore;
import org.eclipse.mylyn.context.core.IInteractionContext;
import org.eclipse.mylyn.context.core.IInteractionElement;
import org.eclipse.mylyn.internal.context.core.ContextCorePlugin;
import org.eclipse.mylyn.internal.context.ui.ContextUiPlugin;
import org.eclipse.mylyn.tasks.ui.TasksUiImages;
import org.eclipse.osgi.util.NLS;
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.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.navigator.CommonViewer;
/**
* @author Shawn Minto
*/
public class InvisibleContextElementsPart {
private static void collectItemData(TreeItem[] items, Set<Object> allVisible) {
for (TreeItem item : items) {
allVisible.add(item.getData());
collectItemData(item.getItems(), allVisible);
}
}
private final class InteractionElementTableSorter extends ViewerSorter {
private int criteria = 0;
private boolean isDecending = true;
private final ITableLabelProvider labelProvider;
public InteractionElementTableSorter(ITableLabelProvider labelProvider) {
this.labelProvider = labelProvider;
}
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
int result = 0;
String value1 = labelProvider.getColumnText(e1, criteria);
String value2 = labelProvider.getColumnText(e2, criteria);
if (value1 == null && value2 != null) {
result = -1;
} else if (value1 != null && value2 == null) {
result = 1;
} else if (value1 != null && value2 != null) {
result = value1.compareTo(value2);
}
return isDecending() ? (result * -1) : result;
}
public boolean isDecending() {
return isDecending;
}
public void setCriteria(int index) {
if (criteria == index) {
isDecending = !isDecending;
} else {
isDecending = false;
}
criteria = index;
}
}
private final AbstractContextListener CONTEXT_LISTENER = new AbstractContextListener() {
@Override
public void contextChanged(ContextChangeEvent event) {
switch (event.getEventKind()) {
case ACTIVATED:
if (isActiveTask()) {
addToolbarActions();
}
break;
case DEACTIVATED:
toolbarManager.removeAll();
toolbarManager.update(true);
}
}
};
private final class InteractionElementTableLabelProvider extends LabelProvider implements ITableLabelProvider {
@Override
public String getText(Object element) {
if (element instanceof IInteractionElement) {
return ((IInteractionElement) element).getHandleIdentifier();
}
return super.getText(element);
}
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
public String getColumnText(Object element, int columnIndex) {
if (element instanceof IInteractionElement) {
if (columnIndex == 0) {
return ((IInteractionElement) element).getHandleIdentifier();
} else if (columnIndex == 1) {
return ((IInteractionElement) element).getContentType();
}
}
return ""; //$NON-NLS-1$
}
}
private final class RemoveInvisibleAction extends Action {
public RemoveInvisibleAction() {
setText(Messages.ContextEditorFormPage_Remove_Invisible_);
setToolTipText(Messages.ContextEditorFormPage_Remove_Invisible_);
setImageDescriptor(TasksUiImages.CONTEXT_CLEAR);
}
@Override
public void run() {
if (commonViewer == null) {
MessageDialog.openWarning(WorkbenchUtil.getShell(), Messages.ContextEditorFormPage_Remove_Invisible,
Messages.ContextEditorFormPage_Activate_task_to_remove_invisible);
return;
}
boolean confirmed = MessageDialog.openConfirm(Display.getCurrent().getActiveShell(),
Messages.ContextEditorFormPage_Remove_Invisible,
Messages.ContextEditorFormPage_Remove_every_element_not_visible);
if (confirmed) {
if (ContextCore.getContextManager().isContextActive()) {
try {
final Collection<Object> allVisible = getAllVisibleElementsInContextPage();
PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException,
InterruptedException {
monitor.beginTask(Messages.InvisibleContextElementsPart_Collecting_all_invisible,
IProgressMonitor.UNKNOWN);
if (allVisible != null) {
final List<IInteractionElement> allToRemove = getAllInvisibleElements(context,
allVisible);
Display.getDefault().asyncExec(new Runnable() {
public void run() {
ContextCorePlugin.getContextManager().deleteElements(allToRemove, true);
}
});
} else {
MessageDialog.openInformation(Display.getCurrent().getActiveShell(),
Messages.ContextEditorFormPage_Remove_Invisible,
Messages.ContextEditorFormPage_No_context_active);
}
}
});
} catch (InvocationTargetException e) {
StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, e.getMessage(), e));
} catch (InterruptedException e) {
StatusHandler.log(new Status(IStatus.ERROR, ContextUiPlugin.ID_PLUGIN, e.getMessage(), e));
}
} else {
MessageDialog.openInformation(Display.getCurrent().getActiveShell(),
Messages.ContextEditorFormPage_Remove_Invisible,
Messages.ContextEditorFormPage_No_context_active);
}
}
}
}
private TableViewer invisibleTable;
private Section invisibleSection;
private CommonViewer commonViewer;
private final IInteractionContext context;
private ToolBarManager toolbarManager;
public InvisibleContextElementsPart(CommonViewer commonViewer) {
this.commonViewer = commonViewer;
context = ContextCore.getContextManager().getActiveContext();
ContextCore.getContextManager().addListener(CONTEXT_LISTENER);
}
public InvisibleContextElementsPart(CommonViewer commonViewer, IInteractionContext context) {
this.commonViewer = commonViewer;
this.context = context;
ContextCore.getContextManager().addListener(CONTEXT_LISTENER);
}
public Control createControl(FormToolkit toolkit, Composite composite) {
invisibleSection = toolkit.createSection(composite, ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE);
invisibleSection.setText(NLS.bind(Messages.InvisibleContextElementsPart_Invisible_elements, "0")); //$NON-NLS-1$
invisibleSection.setEnabled(false);
Composite toolbarComposite = toolkit.createComposite(invisibleSection);
toolbarComposite.setBackground(null);
invisibleSection.setTextClient(toolbarComposite);
RowLayout rowLayout = new RowLayout();
rowLayout.marginTop = 0;
rowLayout.marginBottom = 0;
toolbarComposite.setLayout(rowLayout);
toolbarManager = new ToolBarManager(SWT.FLAT);
toolbarManager.createControl(toolbarComposite);
if (isActiveTask()) {
addToolbarActions();
}
Composite invisibleSectionClient = toolkit.createComposite(invisibleSection);
invisibleSectionClient.setLayout(new GridLayout());
invisibleSection.setClient(invisibleSectionClient);
Composite tableComposite = toolkit.createComposite(invisibleSectionClient);
GridDataFactory.fillDefaults().hint(450, 200).grab(true, false).applyTo(tableComposite);
TableColumnLayout layout = new TableColumnLayout();
tableComposite.setLayout(layout);
invisibleTable = new TableViewer(tableComposite, SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL
| SWT.FULL_SELECTION | SWT.HIDE_SELECTION);
invisibleTable.setColumnProperties(new String[] { Messages.InvisibleContextElementsPart_Structure_handle,
Messages.InvisibleContextElementsPart_Structure_kind });
invisibleTable.getTable().setHeaderVisible(true);
Table table = invisibleTable.getTable();
toolkit.adapt(table);
table.setMenu(null);
InteractionElementTableLabelProvider labelProvider = new InteractionElementTableLabelProvider();
invisibleTable.setLabelProvider(labelProvider);
invisibleTable.setContentProvider(new IStructuredContentProvider() {
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// ignore
}
public void dispose() {
// ignore
}
public Object[] getElements(Object inputElement) {
if (inputElement instanceof Collection<?>) {
return ((Collection<?>) inputElement).toArray();
}
return new Object[0];
}
});
InteractionElementTableSorter invisibleTableSorter = new InteractionElementTableSorter(labelProvider);
invisibleTableSorter.setCriteria(0);
invisibleTable.setSorter(invisibleTableSorter);
createColumn(layout, 0, Messages.InvisibleContextElementsPart_Structure_handle, 340, table,
invisibleTableSorter);
createColumn(layout, 1, Messages.InvisibleContextElementsPart_Structure_kind, 100, table, invisibleTableSorter);
table.setSortColumn(table.getColumn(0));
table.setSortDirection(SWT.DOWN);
Collection<Object> allVisible = getAllVisibleElementsInContextPage();
if (allVisible != null) {
updateInvisibleSectionInBackground(context, allVisible);
}
return invisibleSection;
}
private boolean isActiveTask() {
if (ContextCore.getContextManager().isContextActive()) {
IInteractionContext activeContext = ContextCore.getContextManager().getActiveContext();
if ((context instanceof ContextWrapper && ((ContextWrapper) context).isForSameTaskAs(activeContext))
|| context.equals(activeContext)) {
return true;
}
}
return false;
}
private void addToolbarActions() {
toolbarManager.add(new RemoveInvisibleAction());
toolbarManager.markDirty();
toolbarManager.update(true);
}
private void createColumn(TableColumnLayout layout, final int index, String label, int weight, final Table table,
final InteractionElementTableSorter invisibleTableSorter) {
final TableColumn column = new TableColumn(table, SWT.LEFT, index);
column.setText(label);
column.setToolTipText(label);
column.setResizable(true);
layout.setColumnData(column, new ColumnPixelData(weight, true));
column.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
invisibleTableSorter.setCriteria(index);
table.setSortColumn(column);
if (invisibleTableSorter.isDecending()) {
table.setSortDirection(SWT.UP);
} else {
table.setSortDirection(SWT.DOWN);
}
invisibleTable.refresh();
}
});
}
public void updateInvisibleElementsSection() {
Collection<Object> allVisible = getAllVisibleElementsInContextPage();
if (allVisible != null) {
updateInvisibleSectionInBackground(context, allVisible);
}
}
private void updateInvisibleSectionInBackground(final IInteractionContext context,
final Collection<Object> allVisible) {
Job j = new Job(Messages.InvisibleContextElementsPart_Updating_invisible_element_list) {
@Override
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask(Messages.InvisibleContextElementsPart_Computing_invisible_elements,
IProgressMonitor.UNKNOWN);
final List<IInteractionElement> allInvisibleElements = getAllInvisibleElements(context, allVisible);
Display.getDefault().asyncExec(new Runnable() {
public void run() {
if (invisibleSection != null && !invisibleSection.isDisposed()) {
invisibleSection.setText(NLS.bind(Messages.InvisibleContextElementsPart_Invisible_elements,
allInvisibleElements.size()));
invisibleSection.layout();
if (allInvisibleElements.size() == 0) {
invisibleSection.setExpanded(false);
invisibleSection.setEnabled(false);
} else {
invisibleSection.setEnabled(true);
}
}
if (invisibleTable != null && !invisibleTable.getTable().isDisposed()) {
invisibleTable.setInput(allInvisibleElements);
}
}
});
return Status.OK_STATUS;
};
};
j.schedule();
}
private List<IInteractionElement> getAllInvisibleElements(IInteractionContext context, Collection<Object> allVisible) {
if (context == null || allVisible == null) {
return Collections.emptyList();
}
List<IInteractionElement> allToRemove = context.getAllElements();
List<IInteractionElement> allVisibleElements = new ArrayList<IInteractionElement>();
for (Object visibleObject : allVisible) {
for (AbstractContextStructureBridge bridge : ContextCorePlugin.getDefault().getStructureBridges().values()) {
// AbstractContextStructureBridge bridge = ContextCorePlugin.getDefault().getStructureBridge(visibleObject);
if (bridge != null) {
String handle = bridge.getHandleIdentifier(visibleObject);
if (handle != null) {
IInteractionElement element = context.get(handle);
if (element != null) {
allVisibleElements.add(element);
}
}
}
}
AbstractContextStructureBridge bridge = ContextCorePlugin.getDefault().getStructureBridge(
ContextCore.CONTENT_TYPE_RESOURCE);
if (bridge != null) {
String handle = bridge.getHandleIdentifier(visibleObject);
if (handle != null) {
IInteractionElement element = context.get(handle);
if (element != null) {
allVisibleElements.add(element);
}
}
}
}
IInteractionElement emptyElement = context.get(""); //$NON-NLS-1$
if (emptyElement != null) {
allVisibleElements.add(emptyElement);
}
allToRemove.removeAll(allVisibleElements);
return allToRemove;
}
private Collection<Object> getAllVisibleElementsInContextPage() {
if (commonViewer == null || commonViewer.getTree() == null || commonViewer.getTree().isDisposed()) {
return null;
}
Set<Object> allVisible = new HashSet<Object>();
collectItemData(commonViewer.getTree().getItems(), allVisible);
return allVisible;
}
protected void setCommonViewer(CommonViewer commonViewer) {
this.commonViewer = commonViewer;
updateInvisibleElementsSection();
}
public void dispose() {
ContextCore.getContextManager().removeListener(CONTEXT_LISTENER);
}
}