org.eclipse.egit.ui.internal.push.PushResultTable.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.egit.ui.internal.push.PushResultTable.java

Source

/*******************************************************************************
 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
 *
 * 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.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.egit.core.op.PushOperationResult;
import org.eclipse.egit.ui.UIIcons;
import org.eclipse.egit.ui.UIText;
import org.eclipse.egit.ui.internal.components.CenteredImageLabelProvider;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.ColumnWeightData;
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.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
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.osgi.util.NLS;
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.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;

/**
 * Table displaying push operation results.
 */
class PushResultTable {
    private static final int TABLE_PREFERRED_WIDTH = 650;

    private static final int TABLE_PREFERRED_HEIGHT = 300;

    private static final int TEXT_PREFERRED_HEIGHT = 100;

    private static final int COLUMN_STATUS_WEIGHT = 40;

    private static final int COLUMN_DST_WEIGHT = 40;

    private static final int COLUMN_SRC_WEIGHT = 40;

    private static final int COLUMN_MODE_WEIGHT = 15;

    private static final String IMAGE_DELETE = "MODE_DELETE"; //$NON-NLS-1$

    private static final String IMAGE_ADD = "MODE_ADD"; //$NON-NLS-1$

    private static final String EMPTY_STRING = ""; //$NON-NLS-1$

    private static final String SPACE = " "; //$NON-NLS-1$

    private final TableViewer tableViewer;

    private final Composite tablePanel;

    private final ImageRegistry imageRegistry;

    private ObjectReader reader;

    private Map<ObjectId, String> abbrevations;

    PushResultTable(final Composite parent) {
        tablePanel = new Composite(parent, SWT.NONE);
        tablePanel.setLayout(new GridLayout());
        final GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
        layoutData.heightHint = TABLE_PREFERRED_HEIGHT;
        layoutData.widthHint = TABLE_PREFERRED_WIDTH;
        tableViewer = new TableViewer(tablePanel);
        ColumnViewerToolTipSupport.enableFor(tableViewer);
        final Table table = tableViewer.getTable();
        table.setLinesVisible(true);
        table.setHeaderVisible(true);

        imageRegistry = new ImageRegistry(table.getDisplay());
        imageRegistry.put(IMAGE_ADD, UIIcons.ELCL16_ADD);
        imageRegistry.put(IMAGE_DELETE, UIIcons.ELCL16_DELETE);

        tablePanel.addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
                if (reader != null)
                    reader.release();
                imageRegistry.dispose();
            }
        });

        tableViewer.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();
            }
        });
        tableViewer.setContentProvider(new RefUpdateContentProvider());
        tableViewer.setInput(null);
        // detail message
        final Text text = new Text(parent, SWT.MULTI | SWT.READ_ONLY | SWT.BORDER);
        GridData textLayoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
        textLayoutData.heightHint = TEXT_PREFERRED_HEIGHT;
        text.setLayoutData(textLayoutData);
        tableViewer.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;
                }
                RefUpdateElement element = (RefUpdateElement) structuredSelection.getFirstElement();
                text.setText(getResult(element));
            }
        });
    }

    private String getResult(RefUpdateElement element) {
        StringBuilder result = new StringBuilder(EMPTY_STRING);
        PushOperationResult pushOperationResult = element.getPushOperationResult();
        Set<URIish> urIs = pushOperationResult.getURIs();
        Iterator<URIish> iterator = urIs.iterator();
        while (iterator.hasNext()) {
            boolean lineBreakNeeded = false;
            URIish uri = iterator.next();
            result.append(UIText.PushResultTable_repository);
            result.append(SPACE);
            result.append(uri.toString());
            result.append(Text.DELIMITER);
            result.append(Text.DELIMITER);
            String message = element.getRemoteRefUpdate(uri).getMessage();
            if (message != null) {
                result.append(message);
                result.append(Text.DELIMITER);
                lineBreakNeeded = true;
            }
            StringBuilder messagesBuffer = new StringBuilder(pushOperationResult.getPushResult(uri).getMessages());
            trim(messagesBuffer);
            if (messagesBuffer.length() > 0) {
                result.append(messagesBuffer);
                result.append(Text.DELIMITER);
                lineBreakNeeded = true;
            }
            if (iterator.hasNext() && lineBreakNeeded)
                result.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();
        abbrevations = new HashMap<ObjectId, String>();

        // We have to recreate columns.
        for (final TableColumn tc : tableViewer.getTable().getColumns())
            tc.dispose();
        // Set empty result for a while.
        tableViewer.setInput(null);

        // Layout should be recreated to work properly.
        final TableColumnLayout layout = new TableColumnLayout();
        tablePanel.setLayout(layout);

        final TableViewerColumn modeViewer = createColumn(layout, UIText.PushResultTable_columnMode,
                COLUMN_MODE_WEIGHT, SWT.CENTER);
        modeViewer.setLabelProvider(new CenteredImageLabelProvider() {
            @Override
            public Image getImage(Object element) {
                if (((RefUpdateElement) element).isDelete())
                    return imageRegistry.get(IMAGE_DELETE);
                return imageRegistry.get(IMAGE_ADD);
            }

            @Override
            public String getToolTipText(Object element) {
                if (((RefUpdateElement) element).isDelete())
                    return UIText.RefSpecPanel_modeDeleteDescription;
                return UIText.RefSpecPanel_modeUpdateDescription;
            }
        });

        final TableViewerColumn srcViewer = createColumn(layout, UIText.PushResultTable_columnSrc,
                COLUMN_SRC_WEIGHT, SWT.LEFT);
        srcViewer.setLabelProvider(new ColumnLabelProvider() {
            @Override
            public String getText(Object element) {
                return ((RefUpdateElement) element).getSrcRefName();
            }
        });

        final TableViewerColumn dstViewer = createColumn(layout, UIText.PushResultTable_columnDst,
                COLUMN_DST_WEIGHT, SWT.LEFT);
        dstViewer.setLabelProvider(new ColumnLabelProvider() {
            @Override
            public String getText(Object element) {
                return ((RefUpdateElement) element).getDstRefName();
            }
        });

        if (result == null) {
            tablePanel.layout();
            return;
        }

        int i = 0;
        for (final URIish uri : result.getURIs()) {
            final TableViewerColumn statusViewer = createColumn(layout,
                    NLS.bind(UIText.PushResultTable_columnStatusRepo, Integer.toString(++i)), COLUMN_STATUS_WEIGHT,
                    SWT.LEFT);
            statusViewer.getColumn().setToolTipText(uri.toString());
            statusViewer.setLabelProvider(new UpdateStatusLabelProvider(uri));
        }
        tableViewer.setInput(result);
        // select the first row of table to get the details of the first
        // push result shown in the Text control
        Table table = tableViewer.getTable();
        if (table.getItemCount() > 0) {
            tableViewer.setSelection(new StructuredSelection(table.getItem(0).getData()));
        }
        tablePanel.layout();
    }

    Control getControl() {
        return tablePanel;
    }

    private TableViewerColumn createColumn(final TableColumnLayout columnLayout, final String text,
            final int weight, final int style) {
        final TableViewerColumn viewerColumn = new TableViewerColumn(tableViewer, style);
        final TableColumn column = viewerColumn.getColumn();
        column.setText(text);
        columnLayout.setColumnData(column, new ColumnWeightData(weight));
        return viewerColumn;
    }

    private class UpdateStatusLabelProvider extends ColumnLabelProvider {
        private final URIish uri;

        UpdateStatusLabelProvider(final URIish uri) {
            this.uri = uri;
        }

        @Override
        public String getText(Object element) {
            final RefUpdateElement rue = (RefUpdateElement) element;
            if (!rue.isSuccessfulConnection(uri))
                return UIText.PushResultTable_statusConnectionFailed;

            final RemoteRefUpdate rru = rue.getRemoteRefUpdate(uri);
            switch (rru.getStatus()) {
            case OK:
                if (rru.isDelete())
                    return UIText.PushResultTable_statusOkDeleted;

                final Ref oldRef = rue.getAdvertisedRemoteRef(uri);
                if (oldRef == null) {
                    if (rue.getDstRefName().startsWith(Constants.R_TAGS))
                        return UIText.PushResultTable_statusOkNewTag;
                    return UIText.PushResultTable_statusOkNewBranch;
                }

                return safeAbbreviate(oldRef.getObjectId()) + (rru.isFastForward() ? ".." : "...") //$NON-NLS-1$ //$NON-NLS-2$
                        + safeAbbreviate(rru.getNewObjectId());
            case UP_TO_DATE:
                return UIText.PushResultTable_statusUpToDate;
            case NON_EXISTING:
                return UIText.PushResultTable_statusNoMatch;
            case REJECTED_NODELETE:
            case REJECTED_NONFASTFORWARD:
            case REJECTED_REMOTE_CHANGED:
                return UIText.PushResultTable_statusRejected;
            case REJECTED_OTHER_REASON:
                return UIText.PushResultTable_statusRemoteRejected;
            default:
                throw new IllegalArgumentException(
                        NLS.bind(UIText.PushResultTable_statusUnexpected, rru.getStatus()));
            }
        }

        private String safeAbbreviate(ObjectId id) {
            String abbrev = abbrevations.get(id);
            if (abbrev == null) {
                try {
                    abbrev = reader.abbreviate(id).name();
                } catch (IOException cannotAbbreviate) {
                    abbrev = id.name();
                }
                abbrevations.put(id, abbrev);
            }
            return abbrev;
        }

        @Override
        public Image getImage(Object element) {
            final RefUpdateElement rue = (RefUpdateElement) element;
            if (!rue.isSuccessfulConnection(uri))
                return imageRegistry.get(IMAGE_DELETE);
            final Status status = rue.getRemoteRefUpdate(uri).getStatus();
            switch (status) {
            case OK:
                return null; // no icon for ok
            case UP_TO_DATE:
            case NON_EXISTING:
                return null; // no icon for up to date
            case REJECTED_NODELETE:
            case REJECTED_NONFASTFORWARD:
            case REJECTED_REMOTE_CHANGED:
            case REJECTED_OTHER_REASON:
                return imageRegistry.get(IMAGE_DELETE);
            default:
                throw new IllegalArgumentException(NLS.bind(UIText.PushResultTable_statusUnexpected, status));
            }
        }

        @Override
        public String getToolTipText(Object element) {
            final RefUpdateElement rue = (RefUpdateElement) element;
            if (!rue.isSuccessfulConnection(uri))
                return rue.getErrorMessage(uri);

            final RemoteRefUpdate rru = rue.getRemoteRefUpdate(uri);
            final Ref oldRef = rue.getAdvertisedRemoteRef(uri);
            switch (rru.getStatus()) {
            case OK:
                if (rru.isDelete())
                    return NLS.bind(UIText.PushResultTable_statusDetailDeleted,
                            safeAbbreviate(oldRef.getObjectId()));
                if (oldRef == null)
                    return null;
                if (rru.isFastForward())
                    return UIText.PushResultTable_statusDetailFastForward;
                return UIText.PushResultTable_statusDetailForcedUpdate;
            case UP_TO_DATE:
                return null;
            case NON_EXISTING:
                return UIText.PushResultTable_statusDetailNonExisting;
            case REJECTED_NODELETE:
                return UIText.PushResultTable_statusDetailNoDelete;
            case REJECTED_NONFASTFORWARD:
                return UIText.PushResultTable_statusDetailNonFastForward;
            case REJECTED_REMOTE_CHANGED:
                final Ref remoteRef = oldRef;
                final String curVal;
                if (remoteRef == null)
                    curVal = UIText.PushResultTable_refNonExisting;
                else
                    curVal = safeAbbreviate(remoteRef.getObjectId());

                final ObjectId expectedOldObjectId = rru.getExpectedOldObjectId();
                final String expVal;
                if (expectedOldObjectId.equals(ObjectId.zeroId()))
                    expVal = UIText.PushResultTable_refNonExisting;
                else
                    expVal = safeAbbreviate(expectedOldObjectId);
                return NLS.bind(UIText.PushResultTable_statusDetailChanged, curVal, expVal);
            case REJECTED_OTHER_REASON:
                return rru.getMessage();
            default:
                throw new IllegalArgumentException(
                        NLS.bind(UIText.PushResultTable_statusUnexpected, rru.getStatus()));
            }
        }
    }
}