blob: 6d915322d2e93b99d3cd35927b7042b478390590 [file] [log] [blame]
package org.eclipse.compare.internal.patch;
import java.util.ResourceBundle;
import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.internal.INavigatable;
import org.eclipse.compare.internal.IOpenable;
import org.eclipse.compare.internal.Utilities;
import org.eclipse.compare.structuremergeviewer.IDiffContainer;
import org.eclipse.compare.structuremergeviewer.IDiffElement;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer;
public class CheckboxDiffTreeViewer extends ContainerCheckedTreeViewer {
class CheckboxDiffViewerContentProvider implements ITreeContentProvider {
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// empty implementation
}
public boolean isDeleted(Object element) {
return false;
}
public void dispose() {
inputChanged(CheckboxDiffTreeViewer.this, getInput(), null);
}
public Object getParent(Object element) {
if (element instanceof IDiffElement)
return ((IDiffElement)element).getParent();
return null;
}
public final boolean hasChildren(Object element) {
if (element instanceof IDiffContainer)
return ((IDiffContainer)element).hasChildren();
return false;
}
public final Object[] getChildren(Object element) {
if (element instanceof IDiffContainer)
return ((IDiffContainer)element).getChildren();
return new Object[0];
}
public Object[] getElements(Object element) {
return getChildren(element);
}
}
/*
* Takes care of swapping left and right if fLeftIsLocal
* is true.
*/
class CheckboxDiffViewerLabelProvider extends LabelProvider {
public String getText(Object element) {
if (element instanceof IDiffElement)
return ((IDiffElement)element).getName();
return Utilities.getString(fBundle, "defaultLabel"); //$NON-NLS-1$
}
public Image getImage(Object element) {
if (element instanceof IDiffElement) {
IDiffElement input= (IDiffElement) element;
return input.getImage();
}
return null;
}
}
CompareConfiguration fCompareConfiguration;
private ResourceBundle fBundle;
public CheckboxDiffTreeViewer(Composite parent, CompareConfiguration compareConfiguration) {
super(parent);
initialize(compareConfiguration);
}
private void initialize(CompareConfiguration compareConfiguration) {
Control tree= getControl();
INavigatable nav= new INavigatable() {
public boolean gotoDifference(boolean next) {
// Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
return internalNavigate(next, true);
}
};
tree.setData(INavigatable.NAVIGATOR_PROPERTY, nav);
// Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
IOpenable openable= new IOpenable() {
public void openSelected() {
internalOpen();
}
};
tree.setData(IOpenable.OPENABLE_PROPERTY, openable);
fBundle= ResourceBundle.getBundle("org.eclipse.compare.structuremergeviewer.DiffTreeViewerResources"); //$NON-NLS-1$
setContentProvider(new CheckboxDiffViewerContentProvider());
setLabelProvider(new CheckboxDiffViewerLabelProvider());
addSelectionChangedListener(
new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent se) {
//updateActions();
}
}
);
}
/**
* Selects the next (or previous) node of the current selection.
* If there is no current selection the first (last) node in the tree is selected.
* Wraps around at end or beginning.
* Clients may override.
*
* @param next if <code>true</code> the next node is selected, otherwise the previous node
* @param fireOpen if <code>true</code> an open event is fired.
* @return <code>true</code> if at end (or beginning)
*/
private boolean internalNavigate(boolean next, boolean fireOpen) {
Control c= getControl();
if (!(c instanceof Tree))
return false;
Tree tree= (Tree) c;
TreeItem item= null;
TreeItem children[]= tree.getSelection();
if (children != null && children.length > 0)
item= children[0];
if (item == null) {
children= tree.getItems();
if (children != null && children.length > 0) {
item= children[0];
if (item != null && item.getItemCount() <= 0) {
internalSetSelection(item, fireOpen); // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
return false;
}
}
}
while (true) {
item= findNextPrev(item, next);
if (item == null)
break;
if (item.getItemCount() <= 0)
break;
}
if (item != null) {
internalSetSelection(item, fireOpen); // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
return false;
}
return true;
}
private TreeItem findNextPrev(TreeItem item, boolean next) {
if (item == null)
return null;
TreeItem children[]= null;
if (!next) {
TreeItem parent= item.getParentItem();
if (parent != null)
children= parent.getItems();
else
children= item.getParent().getItems();
if (children != null && children.length > 0) {
// goto previous child
int index= 0;
for (; index < children.length; index++)
if (children[index] == item)
break;
if (index > 0) {
item= children[index-1];
while (true) {
createChildren(item);
int n= item.getItemCount();
if (n <= 0)
break;
item.setExpanded(true);
item= item.getItems()[n-1];
}
// previous
return item;
}
}
// go up
item= parent;
} else {
item.setExpanded(true);
createChildren(item);
if (item.getItemCount() > 0) {
// has children: go down
children= item.getItems();
return children[0];
}
while (item != null) {
children= null;
TreeItem parent= item.getParentItem();
if (parent != null)
children= parent.getItems();
else
children= item.getParent().getItems();
if (children != null && children.length > 0) {
// goto next child
int index= 0;
for (; index < children.length; index++)
if (children[index] == item)
break;
if (index < children.length-1) {
// next
return children[index+1];
}
}
// go up
item= parent;
}
}
return item;
}
private void internalSetSelection(TreeItem ti, boolean fireOpen) {
if (ti != null) {
Object data= ti.getData();
if (data != null) {
// Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
ISelection selection= new StructuredSelection(data);
setSelection(selection, true);
ISelection currentSelection= getSelection();
if (fireOpen && currentSelection != null && selection.equals(currentSelection)) {
fireOpen(new OpenEvent(this, selection));
}
}
}
}
/*
* Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=20106
*/
private void internalOpen() {
ISelection selection= getSelection();
if (selection != null && !selection.isEmpty()) {
fireOpen(new OpenEvent(this, selection));
}
}
/**
* Creates a new DecoratingLabelProvider (using the passed in ILabelDecorator) and sets
* it as the label provider for the tree
* @param decorator
*/
public void setLabelDecorator(ILabelDecorator decorator) {
setLabelProvider(new DecoratingLabelProvider(new CheckboxDiffViewerLabelProvider(), decorator));
}
}