Package org.eclipse.egit.ui.internal.rebase

Source Code of org.eclipse.egit.ui.internal.rebase.RebaseInteractiveView$PlanViewerSelectionChangedListener

/*******************************************************************************
* Copyright (c) 2013, 2014 SAP AG 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
*
* Contributors:
*    Tobias Pfeifer (SAP AG) - initial implementation
*******************************************************************************/
package org.eclipse.egit.ui.internal.rebase;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.egit.core.AdapterUtils;
import org.eclipse.egit.core.RepositoryUtil;
import org.eclipse.egit.core.internal.rebase.RebaseInteractivePlan;
import org.eclipse.egit.core.internal.rebase.RebaseInteractivePlan.ElementAction;
import org.eclipse.egit.core.internal.rebase.RebaseInteractivePlan.ElementType;
import org.eclipse.egit.core.internal.rebase.RebaseInteractivePlan.PlanElement;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.UIUtils;
import org.eclipse.egit.ui.internal.CommonUtils;
import org.eclipse.egit.ui.internal.UIIcons;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.egit.ui.internal.actions.BooleanPrefAction;
import org.eclipse.egit.ui.internal.commands.shared.AbortRebaseCommand;
import org.eclipse.egit.ui.internal.commands.shared.AbstractRebaseCommandHandler;
import org.eclipse.egit.ui.internal.commands.shared.ContinueRebaseCommand;
import org.eclipse.egit.ui.internal.commands.shared.ProcessStepsRebaseCommand;
import org.eclipse.egit.ui.internal.commands.shared.SkipRebaseCommand;
import org.eclipse.egit.ui.internal.commit.CommitEditor;
import org.eclipse.egit.ui.internal.commit.RepositoryCommit;
import org.eclipse.egit.ui.internal.repository.RepositoriesView;
import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.preference.IPersistentPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
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.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.GitDateFormatter;
import org.eclipse.jgit.util.GitDateFormatter.Format;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.part.ViewPart;

/**
* View visualizing git interactive rebase
*/
public class RebaseInteractiveView extends ViewPart implements
    RebaseInteractivePlan.RebaseInteractivePlanChangeListener {

  /**
   * interactive rebase view id
   */
  public static final String VIEW_ID = "org.eclipse.egit.ui.InteractiveRebaseView"; //$NON-NLS-1$

  TreeViewer planTreeViewer;

  private RebaseInteractivePlan currentPlan;

  private Repository currentRepository;

  private RebaseInteractiveStepActionToolBarProvider actionToolBarProvider;

  private ToolItem startItem;

  private ToolItem abortItem;

  private ToolItem skipItem;

  private ToolItem continueItem;

  private ToolItem refreshItem;

  private boolean listenOnRepositoryViewSelection = true;

  private ISelectionListener selectionChangedListener;

  private boolean dndEnabled = false;

  private Form form;

  private LocalResourceManager resources = new LocalResourceManager(
      JFaceResources.getResources());

  private GitDateFormatter dateFormatter = getNewDateFormatter();

  /** these columns are dynamically resized to fit their contents */
  private TreeViewerColumn[] dynamicColumns;

  private List<PlanContextMenuAction> contextMenuItems;

  private RebasePlanIndexer planIndexer;

  private IPreferenceChangeListener prefListener;

  /**
   * View for handling interactive rebase
   */
  public RebaseInteractiveView() {
    setPartName(UIText.InteractiveRebaseView_this_partName);
  }

  /**
   * Set the view input if the passed object can be used to determine the
   * current repository
   *
   * @param o
   */
  public void setInput(Object o) {
    if (o == null)
      return;

    if (o instanceof StructuredSelection) {
      StructuredSelection sel = (StructuredSelection) o;
      if (sel.size() != 1)
        return;
      o = sel.getFirstElement();
    }
    Repository repo = null;
    if (o instanceof RepositoryTreeNode<?>)
      repo = ((RepositoryTreeNode) o).getRepository();
    else if (o instanceof Repository)
      repo = (Repository) o;
    else if (o instanceof IAdaptable) {
      IResource resource = (IResource) ((IAdaptable) o)
          .getAdapter(IResource.class);
      if (resource != null) {
        RepositoryMapping mapping = RepositoryMapping
            .getMapping(resource);
        if (mapping == null)
          return;

        repo = mapping.getRepository();
      }
    }
    if (repo == null)
      repo = AdapterUtils.adapt(o, Repository.class);

    currentRepository = repo;
    showRepository(repo);
  }

  /**
   * @return {@link RebaseInteractiveView#currentPlan}
   */
  public RebaseInteractivePlan getCurrentPlan() {
    return currentPlan;
  }

  @Override
  public void dispose() {
    removeListeners();
    resources.dispose();
    super.dispose();
  }

  private void removeListeners() {
    ISelectionService srv = CommonUtils.getService(getSite(), ISelectionService.class);
    srv.removePostSelectionListener(RepositoriesView.VIEW_ID,
        selectionChangedListener);
    if (currentPlan != null)
      currentPlan.removeRebaseInteractivePlanChangeListener(this);

    if (planIndexer != null)
      planIndexer.dispose();

    InstanceScope.INSTANCE.getNode(
        org.eclipse.egit.core.Activator.getPluginId())
        .removePreferenceChangeListener(prefListener);
  }

  @Override
  public void createPartControl(Composite parent) {
    GridLayoutFactory.fillDefaults().applyTo(parent);
    final FormToolkit toolkit = new FormToolkit(parent.getDisplay());
    parent.addDisposeListener(new DisposeListener() {

      public void widgetDisposed(DisposeEvent e) {
        toolkit.dispose();
      }
    });
    form = createForm(parent, toolkit);
    createCommandToolBar(form, toolkit);
    SashForm sashForm = createRebasePlanSashForm(form, toolkit);

    Section rebasePlanSection = toolkit.createSection(sashForm,
        ExpandableComposite.TITLE_BAR);
    planTreeViewer = createPlanTreeViewer(rebasePlanSection, toolkit);

    createColumns();
    createStepActionToolBar(rebasePlanSection, toolkit);
    createPopupMenu(planTreeViewer);

    setupListeners();
    createLocalDragandDrop();
    planTreeViewer.addDoubleClickListener(new IDoubleClickListener() {

      public void doubleClick(DoubleClickEvent event) {
        PlanElement element = (PlanElement) ((IStructuredSelection) event
            .getSelection()).getFirstElement();
        if (element == null)
          return;

        RepositoryCommit commit = loadCommit(element.getCommit());
        if (commit != null)
          CommitEditor.openQuiet(commit);

      }

      private RepositoryCommit loadCommit(
          AbbreviatedObjectId abbreviatedObjectId) {
        if (abbreviatedObjectId != null) {
          RevWalk walk = new RevWalk(
              RebaseInteractiveView.this.currentRepository);
          try {
            Collection<ObjectId> resolved = walk.getObjectReader()
                .resolve(abbreviatedObjectId);
            if (resolved.size() == 1) {
              RevCommit commit = walk.parseCommit(resolved
                  .iterator().next());
              return new RepositoryCommit(
                  RebaseInteractiveView.this.currentRepository,
                  commit);
            }
          } catch (IOException e) {
            return null;
          } finally {
            walk.release();
          }
        }
        return null;
      }
    });

    prefListener = new IPreferenceChangeListener() {
      public void preferenceChange(PreferenceChangeEvent event) {
        if (!RepositoryUtil.PREFS_DIRECTORIES.equals(event.getKey()))
          return;

        final Repository repo = currentRepository;
        if (repo == null)
          return;

        if (Activator.getDefault().getRepositoryUtil().contains(repo))
          return;

        // Unselect repository as it has been removed
        Display.getDefault().asyncExec(new Runnable() {
          public void run() {
            currentRepository = null;
            showRepository(null);
          }
        });
      }
    };

    InstanceScope.INSTANCE.getNode(
        org.eclipse.egit.core.Activator.getPluginId())
        .addPreferenceChangeListener(prefListener);

    IActionBars actionBars = getViewSite().getActionBars();
    IToolBarManager toolbar = actionBars.getToolBarManager();

    listenOnRepositoryViewSelection = RebaseInteractivePreferences
        .isReactOnSelection();

    // link with selection
    Action linkSelectionAction = new BooleanPrefAction(
        (IPersistentPreferenceStore) Activator.getDefault()
            .getPreferenceStore(),
        UIPreferences.REBASE_INTERACTIVE_SYNC_SELECTION,
        UIText.InteractiveRebaseView_LinkSelection) {
      @Override
      public void apply(boolean value) {
        listenOnRepositoryViewSelection = value;
      }
    };
    linkSelectionAction.setImageDescriptor(UIIcons.ELCL16_SYNCED);
    toolbar.add(linkSelectionAction);
  }

  private void createCommandToolBar(Form theForm, FormToolkit toolkit) {
    ToolBar toolBar = new ToolBar(theForm.getHead(), SWT.FLAT);
    toolBar.setOrientation(SWT.RIGHT_TO_LEFT);
    theForm.setHeadClient(toolBar);

    toolkit.adapt(toolBar);
    toolkit.paintBordersFor(toolBar);

    startItem = new ToolItem(toolBar, SWT.NONE);
    startItem.setImage(UIIcons.getImage(resources,
        UIIcons.REBASE_PROCESS_STEPS));
    startItem.addSelectionListener(new RebaseCommandItemSelectionListener(
        new ProcessStepsRebaseCommand()));
    startItem.setEnabled(false);
    startItem.setText(UIText.InteractiveRebaseView_startItem_text);

    continueItem = new ToolItem(toolBar, SWT.NONE);
    continueItem.setImage(UIIcons.getImage(resources,
        UIIcons.REBASE_CONTINUE));
    continueItem
        .addSelectionListener(new RebaseCommandItemSelectionListener(
            new ContinueRebaseCommand()));
    continueItem.setEnabled(false);
    continueItem.setText(UIText.InteractiveRebaseView_continueItem_text);

    skipItem = new ToolItem(toolBar, SWT.NONE);
    skipItem.setImage(UIIcons.getImage(resources, UIIcons.REBASE_SKIP));
    skipItem.addSelectionListener(new RebaseCommandItemSelectionListener(
        new SkipRebaseCommand()));
    skipItem.setText(UIText.InteractiveRebaseView_skipItem_text);
    skipItem.setEnabled(false);

    abortItem = new ToolItem(toolBar, SWT.NONE);
    abortItem.setImage(UIIcons.getImage(resources, UIIcons.REBASE_ABORT));
    abortItem.addSelectionListener(new RebaseCommandItemSelectionListener(
        new AbortRebaseCommand()));
    abortItem.setText(UIText.InteractiveRebaseView_abortItem_text);
    abortItem.setEnabled(false);

    createSeparator(toolBar);

    refreshItem = new ToolItem(toolBar, SWT.NONE);
    refreshItem.setImage(UIIcons
        .getImage(resources, UIIcons.ELCL16_REFRESH));
    refreshItem.addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        refresh();
      }
    });
    refreshItem.setText(UIText.InteractiveRebaseView_refreshItem_text);
  }

  private static ToolItem createSeparator(ToolBar toolBar) {
    return new ToolItem(toolBar, SWT.SEPARATOR);
  }

  private TreeViewer createPlanTreeViewer(Section rebasePlanSection,
      FormToolkit toolkit) {

    Composite rebasePlanTableComposite = toolkit
        .createComposite(rebasePlanSection);
    toolkit.paintBordersFor(rebasePlanTableComposite);
    rebasePlanSection.setClient(rebasePlanTableComposite);
    GridLayoutFactory.fillDefaults().extendedMargins(2, 2, 2, 2)
        .applyTo(rebasePlanTableComposite);

    Composite toolbarComposite = toolkit.createComposite(rebasePlanSection);
    toolbarComposite.setBackground(null);
    RowLayout toolbarRowLayout = new RowLayout();
    toolbarRowLayout.marginHeight = 0;
    toolbarRowLayout.marginWidth = 0;
    toolbarRowLayout.marginTop = 0;
    toolbarRowLayout.marginBottom = 0;
    toolbarRowLayout.marginLeft = 0;
    toolbarRowLayout.marginRight = 0;
    toolbarComposite.setLayout(toolbarRowLayout);

    GridLayoutFactory.fillDefaults().extendedMargins(2, 2, 2, 2)
        .applyTo(rebasePlanTableComposite);

    final Tree planTree = toolkit.createTree(rebasePlanTableComposite,
        SWT.FULL_SELECTION | SWT.MULTI);
    planTree.setHeaderVisible(true);
    planTree.setLinesVisible(false);

    TreeViewer viewer = new TreeViewer(planTree);
    viewer.addSelectionChangedListener(new PlanViewerSelectionChangedListener());
    GridDataFactory.fillDefaults().grab(true, true)
        .applyTo(viewer.getControl());
    viewer.getTree().setData(FormToolkit.KEY_DRAW_BORDER,
        FormToolkit.TREE_BORDER);
    viewer.setContentProvider(RebaseInteractivePlanContentProvider.INSTANCE);
    return viewer;
  }

  private SashForm createRebasePlanSashForm(final Form parent,
      final FormToolkit toolkit) {
    SashForm sashForm = new SashForm(parent.getBody(), SWT.NONE);
    toolkit.adapt(sashForm, true, true);
    GridDataFactory.fillDefaults().grab(true, true).applyTo(sashForm);
    return sashForm;
  }

  private Form createForm(Composite parent, final FormToolkit toolkit) {
    Form newForm = toolkit.createForm(parent);

    Image repoImage = UIIcons.REPOSITORY.createImage();
    UIUtils.hookDisposal(newForm, repoImage);
    newForm.setImage(repoImage);
    newForm.setText(UIText.RebaseInteractiveView_NoSelection);
    GridDataFactory.fillDefaults().grab(true, true).applyTo(newForm);
    toolkit.decorateFormHeading(newForm);
    GridLayoutFactory.swtDefaults().applyTo(newForm.getBody());

    return newForm;
  }

  private void setupListeners() {
    setupRepositoryViewSelectionChangeListener();
    refreshUI();
  }

  private void setupRepositoryViewSelectionChangeListener() {
    selectionChangedListener = new ISelectionListener() {

      public void selectionChanged(IWorkbenchPart part,
          ISelection selection) {
        if (!listenOnRepositoryViewSelection
            || part == getSite().getPart())
          return;

        // this may happen if we switch between editors
        if (part instanceof IEditorPart) {
          IEditorInput input = ((IEditorPart) part).getEditorInput();
          if (input instanceof IFileEditorInput)
            setInput(new StructuredSelection(
                ((IFileEditorInput) input).getFile()));
        } else
          setInput(selection);
      }
    };

    ISelectionService srv = CommonUtils.getService(getSite(), ISelectionService.class);
    srv.addPostSelectionListener(selectionChangedListener);
  }

  private class RebaseCommandItemSelectionListener extends SelectionAdapter {

    private final AbstractRebaseCommandHandler command;

    public RebaseCommandItemSelectionListener(
        AbstractRebaseCommandHandler command) {
      super();
      this.command = command;
    }

    @Override
    public void widgetSelected(SelectionEvent sEvent) {
      try {
        command.execute(currentPlan.getRepository());
      } catch (ExecutionException e) {
        Activator.showError(e.getMessage(), e);
      }
    }
  }

  private class PlanViewerSelectionChangedListener implements
      ISelectionChangedListener {

    public void selectionChanged(SelectionChangedEvent event) {
      if (event == null)
        return;
      ISelection selection = event.getSelection();
      actionToolBarProvider.mapActionItemsToSelection(selection);
    }
  }

  private void createLocalDragandDrop() {
    planTreeViewer.addDragSupport(DND.DROP_MOVE | DND.DROP_COPY
        | DND.DROP_LINK,
        new Transfer[] { LocalSelectionTransfer.getTransfer() },
        new RebaseInteractiveDragSourceListener(this));
    planTreeViewer.addDropSupport(DND.DROP_MOVE,
        new Transfer[] { LocalSelectionTransfer.getTransfer() },
        new RebaseInteractiveDropTargetListener(this, planTreeViewer));
  }

  private void createStepActionToolBar(Section rebasePlanSection,
      final FormToolkit toolkit) {
    actionToolBarProvider = new RebaseInteractiveStepActionToolBarProvider(
        rebasePlanSection, SWT.FLAT | SWT.WRAP, this);
    toolkit.adapt(actionToolBarProvider.getTheToolbar());
    toolkit.paintBordersFor(actionToolBarProvider.getTheToolbar());
    rebasePlanSection.setTextClient(actionToolBarProvider.getTheToolbar());
  }

  private static RebaseInteractivePlan.ElementType getType(Object element) {
    if (element instanceof PlanElement) {
      PlanElement planLine = (PlanElement) element;
      return planLine.getElementType();
    } else
      return null;
  }

  private static class HighlightingColumnLabelProvider extends
      ColumnLabelProvider {

    @Override
    public Font getFont(Object element) {
      ElementType t = RebaseInteractiveView.getType(element);
      if (t != null && t == ElementType.DONE_CURRENT)
        return UIUtils.getBoldFont(JFaceResources.DIALOG_FONT);
      return super.getFont(element);
    }
  }

  // TODO: How to set column width to fit the treeViewer (maximize to not
  // show empty space)
  private void createColumns() {
    String[] headings = { UIText.RebaseInteractiveView_HeadingStatus,
        UIText.RebaseInteractiveView_HeadingStep,
        UIText.RebaseInteractiveView_HeadingAction,
        UIText.RebaseInteractiveView_HeadingCommitId,
        UIText.RebaseInteractiveView_HeadingMessage,
        UIText.RebaseInteractiveView_HeadingAuthor,
        UIText.RebaseInteractiveView_HeadingAuthorDate,
        UIText.RebaseInteractiveView_HeadingCommitter,
        UIText.RebaseInteractiveView_HeadingCommitDate };

    ColumnViewerToolTipSupport.enableFor(planTreeViewer,
        ToolTip.NO_RECREATE);

    TreeViewerColumn infoColumn = createColumn(headings[0], 70);
    infoColumn.setLabelProvider(new HighlightingColumnLabelProvider() {

      @Override
      public Image getImage(Object element) {
        ElementType t = getType(element);
        if (t != null) {
          switch (t) {
          case DONE_CURRENT:
            return UIIcons
                .getImage(resources, UIIcons.CURRENT_STEP);
          case DONE:
            return UIIcons.getImage(resources, UIIcons.DONE_STEP);
          default:
            // fall through
          }
        }
        return null;
      }

      @Override
      public String getToolTipText(Object element) {
        ElementType t = getType(element);
        if (t != null) {
          switch (t) {
          case DONE:
            return UIText.RebaseInteractiveView_StatusDone;
          case DONE_CURRENT:
            return UIText.RebaseInteractiveView_StatusCurrent;
          case TODO:
            return UIText.RebaseInteractiveView_StatusTodo;
          default:
            // fall through
          }
        }
        return ""; //$NON-NLS-1$
      }

      @Override
      public String getText(Object element) {
        return ""; //$NON-NLS-1$
      }
    });

    TreeViewerColumn stepColumn = createColumn(headings[1], 55);
    stepColumn.setLabelProvider(new HighlightingColumnLabelProvider() {
      @Override
      public String getText(Object element) {
        if (element instanceof PlanElement) {
          PlanElement planLine = (PlanElement) element;
          return (planIndexer.indexOf(planLine) + 1) + "."; //$NON-NLS-1$
        }
        return super.getText(element);
      }
    });
    stepColumn.getColumn().addSelectionListener(new SelectionAdapter() {
      @Override
      public void widgetSelected(SelectionEvent e) {
        Tree tree = planTreeViewer.getTree();

        boolean orderReversed = tree.getSortDirection() == SWT.DOWN;

        RebaseInteractivePreferences.setOrderReversed(!orderReversed);

        int newDirection = (orderReversed ? SWT.UP : SWT.DOWN);
        tree.setSortDirection(newDirection);

        TreeItem topmostVisibleItem = tree.getTopItem();
        refreshUI();
        if (topmostVisibleItem != null)
          tree.showItem(topmostVisibleItem);
      }
    });

    int direction = (RebaseInteractivePreferences.isOrderReversed() ? SWT.DOWN
        : SWT.UP);

    Tree planTree = planTreeViewer.getTree();
    planTree.setSortColumn(stepColumn.getColumn());
    planTree.setSortDirection(direction);

    TreeViewerColumn actionColumn = createColumn(headings[2], 90);
    actionColumn.setLabelProvider(new HighlightingColumnLabelProvider() {

      @Override
      public Image getImage(Object element) {
        ElementAction a = getAction(element);
        if (a != null) {
          switch (a) {
          case EDIT:
            return UIIcons.getImage(resources, UIIcons.EDITCONFIG);
          case FIXUP:
            if (RebaseInteractivePreferences.isOrderReversed())
              return UIIcons.getImage(resources,
                  UIIcons.FIXUP_DOWN);
            else
              return UIIcons.getImage(resources,
                  UIIcons.FIXUP_UP);
          case PICK:
            return UIIcons.getImage(resources, UIIcons.CHERRY_PICK);
          case REWORD:
            return UIIcons.getImage(resources, UIIcons.REWORD);
          case SKIP:
            return UIIcons.getImage(resources, UIIcons.REBASE_SKIP);
          case SQUASH:
            if (RebaseInteractivePreferences.isOrderReversed())
              return UIIcons.getImage(resources,
                  UIIcons.SQUASH_DOWN);
            else
              return UIIcons.getImage(resources,
                  UIIcons.SQUASH_UP);
          default:
            // fall through
          }
        }
        return super.getImage(element);
      }

      @Override
      public String getText(Object element) {
        ElementAction a = getAction(element);
        return (a != null) ? a.name() : super.getText(element);
      }

      private ElementAction getAction(Object element) {
        if (element instanceof PlanElement) {
          PlanElement planLine = (PlanElement) element;
          return planLine.getPlanElementAction();
        } else
          return null;
      }
    });

    TreeViewerColumn commitIDColumn = createColumn(headings[3], 70);
    commitIDColumn.setLabelProvider(new HighlightingColumnLabelProvider() {
      @Override
      public String getText(Object element) {
        if (element instanceof PlanElement) {
          PlanElement planLine = (PlanElement) element;
          return planLine.getCommit().name();
        }
        return super.getText(element);
      }
    });

    TreeViewerColumn commitMessageColumn = createColumn(headings[4], 200);
    commitMessageColumn
        .setLabelProvider(new HighlightingColumnLabelProvider() {
          @Override
          public String getText(Object element) {
            if (element instanceof PlanElement) {
              PlanElement planLine = (PlanElement) element;
              return planLine.getShortMessage();
            }
            return super.getText(element);
          }
        });

    TreeViewerColumn authorColumn = createColumn(headings[5], 120);
    authorColumn.setLabelProvider(new HighlightingColumnLabelProvider() {
      @Override
      public String getText(Object element) {
        if (element instanceof PlanElement) {
          PlanElement planLine = (PlanElement) element;
          return planLine.getAuthor();
        }
        return super.getText(element);
      }
    });

    TreeViewerColumn authoredDateColumn = createColumn(headings[6], 80);
    authoredDateColumn
        .setLabelProvider(new HighlightingColumnLabelProvider() {
          @Override
          public String getText(Object element) {
            if (element instanceof PlanElement) {
              PlanElement planLine = (PlanElement) element;
              return planLine.getAuthoredDate(dateFormatter);
            }
            return super.getText(element);
          }
        });

    TreeViewerColumn committerColumn = createColumn(headings[7], 120);
    committerColumn.setLabelProvider(new HighlightingColumnLabelProvider() {
      @Override
      public String getText(Object element) {
        if (element instanceof PlanElement) {
          PlanElement planLine = (PlanElement) element;
          return planLine.getCommitter();
        }
        return super.getText(element);
      }
    });

    TreeViewerColumn commitDateColumn = createColumn(headings[8], 80);
    commitDateColumn
        .setLabelProvider(new HighlightingColumnLabelProvider() {
          @Override
          public String getText(Object element) {
            if (element instanceof PlanElement) {
              PlanElement planLine = (PlanElement) element;
              return planLine.getCommittedDate(dateFormatter);
            }
            return super.getText(element);
          }
        });
    dynamicColumns = new TreeViewerColumn[] { commitMessageColumn,
        authorColumn, authoredDateColumn, committerColumn,
        commitDateColumn };
  }

  private TreeViewerColumn createColumn(String text, int width) {
    TreeViewerColumn column = new TreeViewerColumn(planTreeViewer, SWT.NONE);
    column.getColumn().setText(text);
    column.getColumn().setMoveable(false);
    column.getColumn().setResizable(true);
    column.getColumn().setWidth(width);
    return column;
  }

  private void asyncExec(Runnable runnable) {
    PlatformUI.getWorkbench().getDisplay().asyncExec(runnable);
  }

  private static String getRepositoryName(Repository repository) {
    String repoName = Activator.getDefault().getRepositoryUtil()
        .getRepositoryName(repository);
    RepositoryState state = repository.getRepositoryState();
    if (state != RepositoryState.SAFE)
      return repoName + '|' + state.getDescription();
    else
      return repoName;
  }

  private void showRepository(final Repository repository) {
    if (form.isDisposed())
      return;

    if (currentPlan != null)
      currentPlan.removeRebaseInteractivePlanChangeListener(this);

    if (planIndexer != null)
      planIndexer.dispose();

    if (isValidRepo(repository)) {
      currentPlan = RebaseInteractivePlan.getPlan(repository);
      planIndexer = new RebasePlanIndexer(currentPlan);
      currentPlan.addRebaseInteractivePlanChangeListener(this);
      form.setText(getRepositoryName(repository));
    } else {
      currentPlan = null;
      planIndexer = null;
      form.setText(UIText.RebaseInteractiveView_NoSelection);
    }
    refresh();
  }

  private boolean isValidRepo(final Repository repository) {
    return repository != null && !repository.isBare()
        && repository.getWorkTree().exists();
  }

  void refresh() {
    if (!isReady())
      return;
    asyncExec(new Runnable() {
      public void run() {
        planTreeViewer.getTree().setRedraw(false);
        try {
          planTreeViewer.setInput(currentPlan);
          refreshUI();
        } finally {
          planTreeViewer.getTree().setRedraw(true);
        }
      }
    });

  }

  private boolean isReady() {
    IWorkbenchPartSite site = this.getSite();
    if (site == null)
      return false;
    return !site.getShell().isDisposed();
  }

  private void refreshUI() {
    dateFormatter = getNewDateFormatter();
    if (planTreeViewer != null) {
      planTreeViewer.refresh(true);
      // make column widths match the contents
      for (TreeViewerColumn col : dynamicColumns)
        col.getColumn().pack();
    }

    startItem.setEnabled(false);
    continueItem.setEnabled(false);
    skipItem.setEnabled(false);
    abortItem.setEnabled(false);
    dndEnabled = false;

    actionToolBarProvider.getTheToolbar().setEnabled(false);

    if (currentPlan == null || !currentPlan.isRebasingInteractive()) {
      if (currentRepository == null)
        form.setText(UIText.RebaseInteractiveView_NoSelection);
      else
        form.setText(getRepositoryName(currentRepository));
      return;
    }

    actionToolBarProvider.mapActionItemsToSelection(planTreeViewer
        .getSelection());
    if (!currentPlan.hasRebaseBeenStartedYet()) {
      if (!planTreeViewer.getSelection().isEmpty())
        actionToolBarProvider.getTheToolbar().setEnabled(true);

      startItem.setEnabled(true);
      abortItem.setEnabled(true);
      dndEnabled = true;
    } else {
      continueItem.setEnabled(true);
      skipItem.setEnabled(true);
      abortItem.setEnabled(true);
    }

    if (RebaseInteractivePreferences.isOrderReversed()) {
      Tree tree = planTreeViewer.getTree();
      int itemCount = tree.getItemCount();
      if (itemCount > 0) {
        TreeItem bottomItem = tree.getItem(itemCount - 1);
        tree.showItem(bottomItem);
      }
    }
  }

  private void createPopupMenu(final TreeViewer planViewer) {
    createContextMenuItems(planViewer);

    MenuManager manager = new MenuManager();
    manager.addMenuListener(new IMenuListener() {
      public void menuAboutToShow(IMenuManager menuManager) {
        boolean selectionNotEmpty = !planViewer.getSelection()
            .isEmpty();
        boolean rebaseNotStarted = !currentPlan
            .hasRebaseBeenStartedYet();
        boolean menuEnabled = selectionNotEmpty && rebaseNotStarted;
        for (PlanContextMenuAction item : contextMenuItems)
          item.setEnabled(menuEnabled);
      }
    });

    for (PlanContextMenuAction item : contextMenuItems)
      manager.add(item);

    Menu menu = manager.createContextMenu(planViewer.getControl());
    planViewer.getControl().setMenu(menu);
  }

  private void createContextMenuItems(final TreeViewer planViewer) {
    contextMenuItems = new ArrayList<PlanContextMenuAction>();

    contextMenuItems.add(new PlanContextMenuAction(
        UIText.RebaseInteractiveStepActionToolBarProvider_PickText,
        UIIcons.CHERRY_PICK, RebaseInteractivePlan.ElementAction.PICK,
        planViewer, actionToolBarProvider));
    contextMenuItems.add(new PlanContextMenuAction(
        UIText.RebaseInteractiveStepActionToolBarProvider_SkipText,
        UIIcons.REBASE_SKIP, RebaseInteractivePlan.ElementAction.SKIP,
        planViewer, actionToolBarProvider));
    contextMenuItems.add(new PlanContextMenuAction(
        UIText.RebaseInteractiveStepActionToolBarProvider_EditText,
        UIIcons.EDITCONFIG, RebaseInteractivePlan.ElementAction.EDIT,
        planViewer, actionToolBarProvider));
    contextMenuItems.add(new PlanContextMenuAction(
        UIText.RebaseInteractiveStepActionToolBarProvider_SquashText,
        UIIcons.SQUASH_UP, RebaseInteractivePlan.ElementAction.SQUASH,
        planViewer, actionToolBarProvider));
    contextMenuItems.add(new PlanContextMenuAction(
        UIText.RebaseInteractiveStepActionToolBarProvider_FixupText,
        UIIcons.FIXUP_UP, RebaseInteractivePlan.ElementAction.FIXUP,
        planViewer, actionToolBarProvider));
    contextMenuItems.add(new PlanContextMenuAction(
        UIText.RebaseInteractiveStepActionToolBarProvider_RewordText,
        UIIcons.REWORD, RebaseInteractivePlan.ElementAction.REWORD,
        planViewer, actionToolBarProvider));
  }

  private static GitDateFormatter getNewDateFormatter() {
    boolean useRelativeDates = Activator.getDefault().getPreferenceStore()
        .getBoolean(UIPreferences.RESOURCEHISTORY_SHOW_RELATIVE_DATE);
    if (useRelativeDates)
      return new GitDateFormatter(Format.RELATIVE);
    else
      return new GitDateFormatter(Format.LOCALE);
  }

  @Override
  public void setFocus() {
    planTreeViewer.getControl().setFocus();
  }

  boolean isDragAndDropEnabled() {
    return dndEnabled;
  }

  public void planWasUpdatedFromRepository(final RebaseInteractivePlan plan) {
    refresh();
  }

  public void planElementTypeChanged(
      RebaseInteractivePlan rebaseInteractivePlan, PlanElement element,
      ElementAction oldType, ElementAction newType) {
    planTreeViewer.refresh(element, true);
  }

  public void planElementsOrderChanged(
      RebaseInteractivePlan rebaseInteractivePlan, PlanElement element,
      int oldIndex, int newIndex) {
    planTreeViewer.refresh(true);
  }
}
TOP

Related Classes of org.eclipse.egit.ui.internal.rebase.RebaseInteractiveView$PlanViewerSelectionChangedListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.