blob: 6a289e1baf7b7fd2c02b24d26f42198fa9628dc9 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2008, 2012 Marek Zawirski <marek.zawirski@gmail.com> 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
*******************************************************************************/
package org.eclipse.egit.ui.internal.push;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.egit.core.op.PushOperationResult;
import org.eclipse.egit.ui.UIUtils;
import org.eclipse.egit.ui.internal.UIIcons;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.egit.ui.internal.WorkbenchStyledLabelProvider;
import org.eclipse.egit.ui.internal.commit.CommitEditor;
import org.eclipse.egit.ui.internal.commit.RepositoryCommit;
import org.eclipse.egit.ui.internal.dialogs.SpellcheckableMessageArea;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider;
import org.eclipse.jface.viewers.IElementComparer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.OpenAndLinkWithEditorHelper;
import org.eclipse.ui.model.IWorkbenchAdapter3;
/**
* Table displaying push operation results.
*/
class PushResultTable {
private static final int TEXT_PREFERRED_HEIGHT = 100;
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
private static final String SPACE = " "; //$NON-NLS-1$
private final TreeViewer treeViewer;
private final Composite root;
private final Image deleteImage;
private ObjectReader reader;
private Repository repo;
PushResultTable(final Composite parent) {
root = new Composite(parent, SWT.NONE);
GridLayoutFactory.swtDefaults().numColumns(2).applyTo(root);
treeViewer = new TreeViewer(root);
treeViewer.setAutoExpandLevel(2);
addToolbar(root);
ColumnViewerToolTipSupport.enableFor(treeViewer);
final Tree table = treeViewer.getTree();
GridDataFactory.fillDefaults().grab(true, true).applyTo(table);
deleteImage = UIIcons.ELCL16_DELETE.createImage();
UIUtils.hookDisposal(root, deleteImage);
root.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (reader != null)
reader.close();
}
});
treeViewer.setComparer(new IElementComparer() {
// we need this to keep refresh() working while having custom
// equals() in PushOperationResult
public boolean equals(Object a, Object b) {
return a == b;
}
public int hashCode(Object element) {
return element.hashCode();
}
});
final IStyledLabelProvider styleProvider = new WorkbenchStyledLabelProvider() {
public StyledString getStyledText(Object element) {
if (element instanceof IWorkbenchAdapter3)
return ((IWorkbenchAdapter3) element).getStyledText(element);
return super.getStyledText(element);
}
};
treeViewer.setSorter(new ViewerSorter() {
public int compare(Viewer viewer, Object e1, Object e2) {
if (e1 instanceof RefUpdateElement
&& e2 instanceof RefUpdateElement) {
RefUpdateElement r1 = (RefUpdateElement) e1;
RefUpdateElement r2 = (RefUpdateElement) e2;
// Put rejected refs first
if (r1.isRejected() && !r2.isRejected())
return -1;
if (!r1.isRejected() && r2.isRejected())
return 1;
// Put new refs next
if (r1.isAdd() && !r2.isAdd())
return -1;
if (!r1.isAdd() && r2.isAdd())
return 1;
// Put branches before tags
if (!r1.isTag() && r2.isTag())
return -1;
if (r1.isTag() && !r2.isTag())
return 1;
Status s1 = r1.getStatus();
Status s2 = r2.getStatus();
// Put up to date refs last
if (s1 != Status.UP_TO_DATE && s2 == Status.UP_TO_DATE)
return -1;
if (s1 == Status.UP_TO_DATE && s2 != Status.UP_TO_DATE)
return 1;
String ref1 = r1.getDstRefName();
String ref2 = r2.getDstRefName();
if (ref1 != null && ref2 != null)
return ref1.compareToIgnoreCase(ref2);
}
// Don't alter commit ordering
if (e1 instanceof RepositoryCommit
&& e2 instanceof RepositoryCommit)
return 0;
return super.compare(viewer, e1, e2);
}
});
treeViewer.setLabelProvider(new DelegatingStyledCellLabelProvider(
styleProvider));
treeViewer.setContentProvider(new RefUpdateContentProvider());
// detail message
Group messageGroup = new Group(root, SWT.NONE);
messageGroup.setText(UIText.PushResultTable_MesasgeText);
GridLayoutFactory.swtDefaults().applyTo(messageGroup);
GridDataFactory.fillDefaults().grab(true, false).span(2, 1)
.applyTo(messageGroup);
final SpellcheckableMessageArea text = new SpellcheckableMessageArea(
messageGroup, EMPTY_STRING, true, SWT.BORDER) {
protected void createMarginPainter() {
// Disabled intentionally
}
};
GridDataFactory.fillDefaults().grab(true, true)
.hint(SWT.DEFAULT, TEXT_PREFERRED_HEIGHT).applyTo(text);
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = event.getSelection();
if (!(selection instanceof IStructuredSelection)) {
text.setText(EMPTY_STRING);
return;
}
IStructuredSelection structuredSelection = (IStructuredSelection) selection;
if (structuredSelection.size() != 1) {
text.setText(EMPTY_STRING);
return;
}
Object selected = structuredSelection.getFirstElement();
if (selected instanceof RefUpdateElement)
text.setText(getResult((RefUpdateElement) selected));
}
});
new OpenAndLinkWithEditorHelper(treeViewer) {
@Override
protected void linkToEditor(ISelection selection) {
// Not supported
}
@Override
protected void open(ISelection selection, boolean activate) {
handleOpen(selection, OpenStrategy.activateOnOpen());
}
@Override
protected void activate(ISelection selection) {
handleOpen(selection, true);
}
private void handleOpen(ISelection selection, boolean activateOnOpen) {
if (selection instanceof IStructuredSelection)
for (Object element : ((IStructuredSelection) selection)
.toArray())
if (element instanceof RepositoryCommit)
CommitEditor.openQuiet((RepositoryCommit) element, activateOnOpen);
}
};
}
private void addToolbar(Composite parent) {
ToolBar toolbar = new ToolBar(parent, SWT.VERTICAL);
GridDataFactory.fillDefaults().grab(false, true).applyTo(toolbar);
UIUtils.addExpansionItems(toolbar, treeViewer);
}
private String getResult(RefUpdateElement element) {
StringBuilder result = new StringBuilder(EMPTY_STRING);
PushOperationResult pushOperationResult = element
.getPushOperationResult();
final URIish uri = element.getUri();
result.append(UIText.PushResultTable_repository);
result.append(SPACE);
result.append(uri.toString());
result.append(Text.DELIMITER);
result.append(Text.DELIMITER);
String message = element.getRemoteRefUpdate().getMessage();
if (message != null)
result.append(message).append(Text.DELIMITER);
StringBuilder messagesBuffer = new StringBuilder(pushOperationResult
.getPushResult(uri).getMessages());
trim(messagesBuffer);
if (messagesBuffer.length() > 0)
result.append(messagesBuffer).append(Text.DELIMITER);
trim(result);
return result.toString();
}
private static void trim(StringBuilder s) {
// remove leading line breaks
while (s.length() > 0 && (s.charAt(0) == '\n' || s.charAt(0) == '\r'))
s.deleteCharAt(0);
// remove trailing line breaks
while (s.length() > 0
&& (s.charAt(s.length() - 1) == '\n' || s
.charAt(s.length() - 1) == '\r'))
s.deleteCharAt(s.length() - 1);
}
void setData(final Repository localDb, final PushOperationResult result) {
reader = localDb.newObjectReader();
repo = localDb;
// Set empty result for a while.
treeViewer.setInput(null);
if (result == null) {
root.layout();
return;
}
final List<RefUpdateElement> results = new ArrayList<RefUpdateElement>();
for (URIish uri : result.getURIs())
if (result.isSuccessfulConnection(uri))
for (RemoteRefUpdate update : result.getPushResult(uri)
.getRemoteUpdates())
results.add(new RefUpdateElement(result, update, uri,
reader, repo));
treeViewer.setInput(results.toArray());
// select the first row of table to get the details of the first
// push result shown in the Text control
Tree table = treeViewer.getTree();
if (table.getItemCount() > 0)
treeViewer.setSelection(new StructuredSelection(table.getItem(0)
.getData()));
root.layout();
}
Control getControl() {
return root;
}
}