gt: 		else if (unstagedViewer != null
context: /*******************************************************************************
   * Copyright (C) 2011, 2015 Bernard Leach <leachbj@bouncycastle.org> 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.staging;
  
  import static org.eclipse.egit.ui.internal.CommonUtils.runCommand;
  
  import java.io.File;
  import java.text.MessageFormat;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.EnumSet;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Set;
  
  import org.eclipse.core.commands.ExecutionException;
  import org.eclipse.core.commands.operations.IUndoContext;
  import org.eclipse.core.resources.IContainer;
  import org.eclipse.core.resources.IFile;
  import org.eclipse.core.resources.IProject;
  import org.eclipse.core.resources.IResource;
  import org.eclipse.core.resources.ResourcesPlugin;
  import org.eclipse.core.runtime.CoreException;
  import org.eclipse.core.runtime.IPath;
  import org.eclipse.core.runtime.IProgressMonitor;
  import org.eclipse.core.runtime.IStatus;
  import org.eclipse.core.runtime.Path;
  import org.eclipse.core.runtime.Status;
  import org.eclipse.core.runtime.jobs.IJobChangeEvent;
  import org.eclipse.core.runtime.jobs.Job;
  import org.eclipse.core.runtime.jobs.JobChangeAdapter;
  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.gerrit.GerritUtil;
  import org.eclipse.egit.core.internal.indexdiff.IndexDiffCacheEntry;
  import org.eclipse.egit.core.internal.indexdiff.IndexDiffChangedListener;
  import org.eclipse.egit.core.internal.indexdiff.IndexDiffData;
  import org.eclipse.egit.core.internal.job.RuleUtil;
  import org.eclipse.egit.core.op.CommitOperation;
  import org.eclipse.egit.core.project.RepositoryMapping;
  import org.eclipse.egit.ui.Activator;
  import org.eclipse.egit.ui.JobFamilies;
  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.EgitUiEditorUtils;
  import org.eclipse.egit.ui.internal.GitLabels;
  import org.eclipse.egit.ui.internal.UIIcons;
  import org.eclipse.egit.ui.internal.UIText;
  import org.eclipse.egit.ui.internal.actions.ActionCommands;
  import org.eclipse.egit.ui.internal.actions.BooleanPrefAction;
  import org.eclipse.egit.ui.internal.actions.ReplaceWithOursTheirsMenu;
  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.SkipRebaseCommand;
  import org.eclipse.egit.ui.internal.commit.CommitHelper;
  import org.eclipse.egit.ui.internal.commit.CommitJob;
  import org.eclipse.egit.ui.internal.commit.CommitMessageHistory;
  import org.eclipse.egit.ui.internal.commit.CommitProposalProcessor;
  import org.eclipse.egit.ui.internal.components.ToggleableWarningLabel;
  import org.eclipse.egit.ui.internal.decorators.ProblemLabelDecorator;
  import org.eclipse.egit.ui.internal.dialogs.CommitMessageArea;
  import org.eclipse.egit.ui.internal.dialogs.CommitMessageComponent;
  import org.eclipse.egit.ui.internal.dialogs.CommitMessageComponentState;
  import org.eclipse.egit.ui.internal.dialogs.CommitMessageComponentStateManager;
  import org.eclipse.egit.ui.internal.dialogs.ICommitMessageComponentNotifications;
  import org.eclipse.egit.ui.internal.dialogs.SpellcheckableMessageArea;
  import org.eclipse.egit.ui.internal.operations.DeletePathsOperationUI;
  import org.eclipse.egit.ui.internal.operations.IgnoreOperationUI;
  import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode;
  import org.eclipse.jface.action.Action;
  import org.eclipse.jface.action.ControlContribution;
  import org.eclipse.jface.action.IAction;
  import org.eclipse.jface.action.IContributionItem;
  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.action.Separator;
  import org.eclipse.jface.action.ToolBarManager;
  import org.eclipse.jface.dialogs.MessageDialog;
  import org.eclipse.jface.layout.GridDataFactory;
  import org.eclipse.jface.layout.GridLayoutFactory;
  import org.eclipse.jface.preference.IPersistentPreferenceStore;
  import org.eclipse.jface.preference.IPreferenceStore;
  import org.eclipse.jface.resource.ImageDescriptor;
  import org.eclipse.jface.resource.JFaceResources;
  import org.eclipse.jface.resource.LocalResourceManager;
  import org.eclipse.jface.util.LocalSelectionTransfer;
  import org.eclipse.jface.viewers.AbstractTreeViewer;
  import org.eclipse.jface.viewers.ContentViewer;
  import org.eclipse.jface.viewers.DecoratingLabelProvider;
  import org.eclipse.jface.viewers.IBaseLabelProvider;
  import org.eclipse.jface.viewers.ILabelDecorator;
  import org.eclipse.jface.viewers.ILabelProvider;
  import org.eclipse.jface.viewers.IOpenListener;
  import org.eclipse.jface.viewers.ISelection;
  import org.eclipse.jface.viewers.ISelectionProvider;
  import org.eclipse.jface.viewers.IStructuredSelection;
  import org.eclipse.jface.viewers.ITreeViewerListener;
  import org.eclipse.jface.viewers.OpenEvent;
  import org.eclipse.jface.viewers.StructuredSelection;
  import org.eclipse.jface.viewers.TreeExpansionEvent;
  import org.eclipse.jface.viewers.TreeViewer;
  import org.eclipse.jface.viewers.Viewer;
  import org.eclipse.jface.viewers.ViewerFilter;
  import org.eclipse.jgit.api.AddCommand;
  import org.eclipse.jgit.api.CheckoutCommand;
  import org.eclipse.jgit.api.Git;
  import org.eclipse.jgit.api.ResetCommand;
  import org.eclipse.jgit.api.RmCommand;
  import org.eclipse.jgit.api.errors.GitAPIException;
  import org.eclipse.jgit.api.errors.JGitInternalException;
  import org.eclipse.jgit.api.errors.NoFilepatternException;
  import org.eclipse.jgit.events.ListenerHandle;
  import org.eclipse.jgit.events.RefsChangedEvent;
  import org.eclipse.jgit.events.RefsChangedListener;
  import org.eclipse.jgit.lib.Constants;
  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.osgi.util.NLS;
  import org.eclipse.swt.SWT;
  import org.eclipse.swt.custom.SashForm;
  import org.eclipse.swt.custom.VerifyKeyListener;
  import org.eclipse.swt.dnd.DND;
  import org.eclipse.swt.dnd.DragSourceAdapter;
  import org.eclipse.swt.dnd.DragSourceEvent;
  import org.eclipse.swt.dnd.DropTargetAdapter;
  import org.eclipse.swt.dnd.DropTargetEvent;
  import org.eclipse.swt.dnd.FileTransfer;
  import org.eclipse.swt.dnd.Transfer;
  import org.eclipse.swt.events.DisposeEvent;
  import org.eclipse.swt.events.DisposeListener;
  import org.eclipse.swt.events.FocusEvent;
  import org.eclipse.swt.events.FocusListener;
  import org.eclipse.swt.events.ModifyEvent;
  import org.eclipse.swt.events.ModifyListener;
  import org.eclipse.swt.events.SelectionAdapter;
  import org.eclipse.swt.events.SelectionEvent;
  import org.eclipse.swt.events.VerifyEvent;
  import org.eclipse.swt.graphics.Image;
  import org.eclipse.swt.layout.GridData;
  import org.eclipse.swt.layout.GridLayout;
  import org.eclipse.swt.layout.RowLayout;
  import org.eclipse.swt.widgets.Button;
  import org.eclipse.swt.widgets.Composite;
  import org.eclipse.swt.widgets.Control;
  import org.eclipse.swt.widgets.Display;
  import org.eclipse.swt.widgets.Label;
  import org.eclipse.swt.widgets.Text;
  import org.eclipse.swt.widgets.Tree;
  import org.eclipse.ui.IActionBars;
  import org.eclipse.ui.IEditorInput;
  import org.eclipse.ui.IEditorPart;
  import org.eclipse.ui.IFileEditorInput;
  import org.eclipse.ui.IPartListener2;
  import org.eclipse.ui.IPartService;
  import org.eclipse.ui.ISelectionListener;
  import org.eclipse.ui.ISelectionService;
  import org.eclipse.ui.IWorkbenchPage;
  import org.eclipse.ui.IWorkbenchPart;
  import org.eclipse.ui.IWorkbenchPartReference;
  import org.eclipse.ui.IWorkbenchPartSite;
  import org.eclipse.ui.IWorkbenchWindow;
  import org.eclipse.ui.PlatformUI;
  import org.eclipse.ui.actions.ActionFactory;
  import org.eclipse.ui.forms.IFormColors;
  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.handlers.IHandlerService;
  import org.eclipse.ui.operations.UndoRedoActionGroup;
  import org.eclipse.ui.part.IShowInSource;
  import org.eclipse.ui.part.ShowInContext;
  import org.eclipse.ui.part.ViewPart;
  import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
  
  /**
   * A GitX style staging view with embedded commit dialog.
   */
  public class StagingView extends ViewPart implements IShowInSource {
  
  	/**
  	 * Staging view id
  	 */
  	public static final String VIEW_ID = "org.eclipse.egit.ui.StagingView"; //$NON-NLS-1$
  
  	private static final String EMPTY_STRING = ""; //$NON-NLS-1$
  
  	private FormToolkit toolkit;
  
  	private Form form;
  
  	private Section stagedSection;
  
  	private Section unstagedSection;
  
  	private Section commitMessageSection;
  
  	private TreeViewer stagedViewer;
  
  	private TreeViewer unstagedViewer;
  
  	private ToggleableWarningLabel warningLabel;
  
  	private Text filterText;
  
  	private SpellcheckableMessageArea commitMessageText;
  
  	private Text committerText;
  
  	private Text authorText;
  
  	private CommitMessageComponent commitMessageComponent;
  
  	private boolean reactOnSelection = true;
  
  	private boolean isViewHidden;
  
  	private ISelectionListener selectionChangedListener;
  
  	private IPartListener2 partListener;
  
  	private ToolBarManager unstagedToolBarManager;
  
  	private ToolBarManager stagedToolBarManager;
  
  	private Action listPresentationAction;
  
  	private Action treePresentationAction;
  
  	private Action compactTreePresentationAction;
  
  	private Action unstagedExpandAllAction;
  
  	private Action unstagedCollapseAllAction;
  
  	private Action stagedExpandAllAction;
  
  	private Action stagedCollapseAllAction;
  
  	private Repository currentRepository;
  
  	private Presentation presentation = Presentation.LIST;
  
  	private Set<IPath> pathsToExpandInStaged = new HashSet<IPath>();
  
  	private Set<IPath> pathsToExpandInUnstaged = new HashSet<IPath>();
  
  	/**
  	 * Presentation mode of the staged/unstaged files.
  	 */
  	public enum Presentation {
  		/** Show files in flat list */
  		LIST,
  		/** Show folder structure in full tree */
  		TREE,
  		/**
  		 * Show folder structure in compact tree (folders with only one child
  		 * are folded into parent)
  		 */
  		COMPACT_TREE;
  	}
  
  	static class StagingViewUpdate {
  		Repository repository;
  		IndexDiffData indexDiff;
  		Collection<String> changedResources;
  
  		StagingViewUpdate(Repository theRepository,
  				IndexDiffData theIndexDiff, Collection<String> theChanges) {
  			this.repository = theRepository;
  			this.indexDiff = theIndexDiff;
  			this.changedResources = theChanges;
  		}
  	}
  
  	static class StagingDragListener extends DragSourceAdapter {
  
  		private ISelectionProvider provider;
  
  		public StagingDragListener(ISelectionProvider provider) {
  			this.provider = provider;
  		}
  
  		@Override
  		public void dragStart(DragSourceEvent event) {
  			event.doit = !provider.getSelection().isEmpty();
  		}
  
  		@Override
  		public void dragFinished(DragSourceEvent event) {
  			if (LocalSelectionTransfer.getTransfer().isSupportedType(
  					event.dataType))
  				LocalSelectionTransfer.getTransfer().setSelection(null);
  		}
  
  		@Override
  		public void dragSetData(DragSourceEvent event) {
  			IStructuredSelection selection = (IStructuredSelection) provider
  					.getSelection();
  			if (selection.isEmpty())
  				return;
  
  			if (LocalSelectionTransfer.getTransfer().isSupportedType(
  					event.dataType)) {
  				LocalSelectionTransfer.getTransfer().setSelection(selection);
  				return;
  			}
  
  			if (FileTransfer.getInstance().isSupportedType(event.dataType)) {
  				List<String> files = new ArrayList<String>();
  				for (Object selected : selection.toList())
  					if (selected instanceof StagingEntry) {
  						StagingEntry entry = (StagingEntry) selected;
  						File file = new File(
  								entry.getRepository().getWorkTree(),
  								entry.getPath());
  						if (file.exists())
  							files.add(file.getAbsolutePath());
  					}
  				if (!files.isEmpty()) {
  					event.data = files.toArray(new String[files.size()]);
  					return;
  				}
  			}
  		}
  	}
  
  	private final class PartListener implements IPartListener2 {
  		StructuredSelection lastSelection;
  
  		@Override
  		public void partVisible(IWorkbenchPartReference partRef) {
  			updateHiddenState(partRef, false);
  		}
  
  		@Override
  		public void partOpened(IWorkbenchPartReference partRef) {
  			updateHiddenState(partRef, false);
  		}
  
  		@Override
  		public void partHidden(IWorkbenchPartReference partRef) {
  			updateHiddenState(partRef, true);
  		}
  
  		@Override
  		public void partClosed(IWorkbenchPartReference partRef) {
  			updateHiddenState(partRef, true);
  		}
  
  		@Override
  		public void partActivated(IWorkbenchPartReference partRef) {
  			if (isMe(partRef)) {
  				if (lastSelection != null) {
  					// view activated: synchronize with last active part
  					// selection
  					reactOnSelection(lastSelection);
  					lastSelection = null;
  				}
  				return;
  			}
  			IWorkbenchPart part = partRef.getPart(false);
  			StructuredSelection sel = null;
  			if (part instanceof IEditorPart) {
  				IResource resource = getResource((IEditorPart) part);
  				if (resource != null) {
  					sel = new StructuredSelection(resource);
  				}
  			} else {
  				ISelection selection = partRef.getPage().getSelection();
  				if (selection instanceof StructuredSelection) {
  					sel = (StructuredSelection) selection;
  				}
  			}
  			if (isViewHidden) {
  				// remember last selection in the part so that we can
  				// synchronize on it as soon as we will be visible
  				lastSelection = sel;
  			} else {
  				lastSelection = null;
  				if (sel != null) {
  					reactOnSelection(sel);
  				}
  			}
  
  		}
  
  		private IResource getResource(IEditorPart part) {
  			IEditorInput input = part.getEditorInput();
  			if (input instanceof IFileEditorInput) {
  				return ((IFileEditorInput) input).getFile();
  			} else {
  				return CommonUtils.getAdapter(input, IResource.class);
  			}
  		}
  
  		private void updateHiddenState(IWorkbenchPartReference partRef,
  				boolean hidden) {
  			if (isMe(partRef)) {
  				isViewHidden = hidden;
  			}
  		}
  
  		private boolean isMe(IWorkbenchPartReference partRef) {
  			return partRef.getPart(false) == StagingView.this;
  		}
  
  		@Override
  		public void partDeactivated(IWorkbenchPartReference partRef) {
  			//
  		}
  
  		@Override
  		public void partBroughtToTop(IWorkbenchPartReference partRef) {
  			//
  		}
  
  		@Override
  		public void partInputChanged(IWorkbenchPartReference partRef) {
  			//
  		}
  	}
  
  	static class TreeDecoratingLabelProvider extends DecoratingLabelProvider {
  
  		ILabelProvider provider;
  
  		ILabelDecorator decorator;
  
  		public TreeDecoratingLabelProvider(ILabelProvider provider,
  				ILabelDecorator decorator) {
  			super(provider, decorator);
  			this.provider = provider;
  			this.decorator = decorator;
  		}
  
  		public Image getColumnImage(Object element) {
  			Image image = provider.getImage(element);
  			if (image != null && decorator != null) {
  				Image decorated = decorator.decorateImage(image, element);
  				if (decorated != null)
  					return decorated;
  			}
  			return image;
  		}
  
  		@Override
  		public String getText(Object element) {
  			return provider.getText(element);
  		}
  	}
  
  	static class StagingViewSearchThread extends Thread {
  		private StagingView stagingView;
  
  		private static final Object lock = new Object();
  
  		private volatile static int globalThreadIndex = 0;
  
  		private int currentThreadIx;
  
  		public StagingViewSearchThread(StagingView stagingView) {
  			super("staging_view_filter_thread" + ++globalThreadIndex); //$NON-NLS-1$
  			this.stagingView = stagingView;
  			currentThreadIx = globalThreadIndex;
  		}
  
  		@Override
  		public void run() {
  			synchronized (lock) {
  				if (currentThreadIx < globalThreadIndex)
  					return;
  				stagingView.refreshViewersPreservingExpandedElements();
  			}
  		}
  
  	}
  
  	private final IPreferenceChangeListener prefListener = new IPreferenceChangeListener() {
  
  		@Override
  		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;
  
  			reload(null);
  		}
  
  	};
  
  	private Action signedOffByAction;
  
  	private Action addChangeIdAction;
  
  	private Action amendPreviousCommitAction;
  
  	private Action openNewCommitsAction;
  
  	private Action columnLayoutAction;
  
  	private Action fileNameModeAction;
  
  	private Action refreshAction;
  
  	private SashForm stagingSashForm;
  
  	private IndexDiffChangedListener myIndexDiffListener = new IndexDiffChangedListener() {
  		@Override
  		public void indexDiffChanged(Repository repository,
  				IndexDiffData indexDiffData) {
  			reload(repository);
  		}
  	};
  
  	private IndexDiffCacheEntry cacheEntry;
  
  	private UndoRedoActionGroup undoRedoActionGroup;
  
  	private Button commitButton;
  
  	private Button commitAndPushButton;
  
  	private Section rebaseSection;
  
  	private Button rebaseContinueButton;
  
  	private Button rebaseSkipButton;
  
  	private Button rebaseAbortButton;
  
  	private ListenerHandle refsChangedListener;
  
  	private LocalResourceManager resources = new LocalResourceManager(
  			JFaceResources.getResources());
  
  	private boolean disposed;
  
  	private Image getImage(ImageDescriptor descriptor) {
  		return (Image) this.resources.get(descriptor);
  	}
  
  	@Override
  	public void createPartControl(Composite parent) {
  		GridLayoutFactory.fillDefaults().applyTo(parent);
  
  		toolkit = new FormToolkit(parent.getDisplay());
  		parent.addDisposeListener(new DisposeListener() {
  
  			@Override
  			public void widgetDisposed(DisposeEvent e) {
  				if (commitMessageComponent.isAmending()
  						|| userEnteredCommitMessage())
  					saveCommitMessageComponentState();
  				else
  					deleteCommitMessageComponentState();
  				resources.dispose();
  				toolkit.dispose();
  			}
  		});
  
  		form = toolkit.createForm(parent);
  
  		form.setImage(getImage(UIIcons.REPOSITORY));
  		form.setText(UIText.StagingView_NoSelectionTitle);
  		GridDataFactory.fillDefaults().grab(true, true).applyTo(form);
  		toolkit.decorateFormHeading(form);
  		GridLayoutFactory.swtDefaults().applyTo(form.getBody());
  
  		SashForm horizontalSashForm = new SashForm(form.getBody(), SWT.NONE);
  		toolkit.adapt(horizontalSashForm, true, true);
  		GridDataFactory.fillDefaults().grab(true, true)
  				.applyTo(horizontalSashForm);
  
  		stagingSashForm = new SashForm(horizontalSashForm,
  				getStagingFormOrientation());
  		toolkit.adapt(stagingSashForm, true, true);
  		GridDataFactory.fillDefaults().grab(true, true)
  				.applyTo(stagingSashForm);
  
  		unstagedSection = toolkit.createSection(stagingSashForm,
  				ExpandableComposite.TITLE_BAR);
  
  		createUnstagedToolBarComposite();
  
  		Composite unstagedComposite = toolkit
  				.createComposite(unstagedSection);
  		toolkit.paintBordersFor(unstagedComposite);
  		unstagedSection.setClient(unstagedComposite);
  		GridLayoutFactory.fillDefaults().extendedMargins(2, 2, 2, 2)
  				.applyTo(unstagedComposite);
  
  		unstagedViewer = createTree(unstagedComposite);
  		GridDataFactory.fillDefaults().grab(true, true)
  				.applyTo(unstagedViewer.getControl());
  		unstagedViewer.getTree().setData(FormToolkit.KEY_DRAW_BORDER,
  				FormToolkit.TREE_BORDER);
  		unstagedViewer.setLabelProvider(createLabelProvider(unstagedViewer));
  		unstagedViewer.setContentProvider(createStagingContentProvider(true));
  		unstagedViewer.addDragSupport(DND.DROP_MOVE | DND.DROP_COPY
  				| DND.DROP_LINK,
  				new Transfer[] { LocalSelectionTransfer.getTransfer(),
  						FileTransfer.getInstance() }, new StagingDragListener(
  						unstagedViewer));
  		unstagedViewer.addDropSupport(DND.DROP_MOVE,
  				new Transfer[] { LocalSelectionTransfer.getTransfer() },
  				new DropTargetAdapter() {
  					@Override
  					public void drop(DropTargetEvent event) {
  						// Bug 411466: It is very important that detail is set
  						// to DND.DROP_COPY. If it was left as DND.DROP_MOVE and
  						// the drag comes from the Navigator view, the code in
  						// NavigatorDragAdapter would delete the resources.
  						event.detail = DND.DROP_COPY;
  						if (event.data instanceof IStructuredSelection) {
  							final IStructuredSelection selection = (IStructuredSelection) event.data;
  							unstage(selection);
  						}
  					}
  
  					@Override
  					public void dragOver(DropTargetEvent event) {
  						event.detail = DND.DROP_MOVE;
  					}
  				});
  		unstagedViewer.addOpenListener(new IOpenListener() {
  			@Override
  			public void open(OpenEvent event) {
  				compareWith(event);
  			}
  		});
  		enableAutoExpand(unstagedViewer);
  		addListenerToDisableAutoExpandOnCollapse(unstagedViewer);
  
  		Composite rebaseAndCommitComposite = toolkit.createComposite(horizontalSashForm);
  		rebaseAndCommitComposite.setLayout(GridLayoutFactory.fillDefaults().create());
  
  		rebaseSection = toolkit.createSection(rebaseAndCommitComposite,
  				ExpandableComposite.TITLE_BAR);
  		rebaseSection.setText(UIText.StagingView_RebaseLabel);
  
  		Composite rebaseComposite = toolkit.createComposite(rebaseSection);
  		toolkit.paintBordersFor(rebaseComposite);
  		rebaseSection.setClient(rebaseComposite);
  
  		rebaseSection.setLayoutData(GridDataFactory.fillDefaults().create());
  		rebaseComposite.setLayout(GridLayoutFactory.fillDefaults()
  				.numColumns(3).equalWidth(true).create());
  		GridDataFactory buttonGridData = GridDataFactory.fillDefaults().align(
  				SWT.FILL, SWT.CENTER);
  
  		this.rebaseAbortButton = toolkit.createButton(rebaseComposite,
  				UIText.StagingView_RebaseAbort, SWT.PUSH);
  		rebaseAbortButton.addSelectionListener(new SelectionAdapter() {
  			@Override
  			public void widgetSelected(SelectionEvent e) {
  				rebaseAbort();
  			}
  		});
  		rebaseAbortButton.setImage(getImage(UIIcons.REBASE_ABORT));
  		buttonGridData.applyTo(rebaseAbortButton);
  
  		this.rebaseSkipButton = toolkit.createButton(rebaseComposite,
  				UIText.StagingView_RebaseSkip, SWT.PUSH);
  		rebaseSkipButton.addSelectionListener(new SelectionAdapter() {
  			@Override
  			public void widgetSelected(SelectionEvent e) {
  				rebaseSkip();
  			}
  		});
  		rebaseSkipButton.setImage(getImage(UIIcons.REBASE_SKIP));
  		buttonGridData.applyTo(rebaseSkipButton);
  
  		this.rebaseContinueButton = toolkit.createButton(rebaseComposite,
  				UIText.StagingView_RebaseContinue, SWT.PUSH);
  		rebaseContinueButton.addSelectionListener(new SelectionAdapter() {
  			@Override
  			public void widgetSelected(SelectionEvent e) {
  				rebaseContinue();
  			}
  		});
  		rebaseContinueButton.setImage(getImage(UIIcons.REBASE_CONTINUE));
  		buttonGridData.applyTo(rebaseContinueButton);
  
  		showControl(rebaseSection, false);
  
  		commitMessageSection = toolkit.createSection(rebaseAndCommitComposite,
  				ExpandableComposite.TITLE_BAR);
  		commitMessageSection.setText(UIText.StagingView_CommitMessage);
  		commitMessageSection.setLayoutData(GridDataFactory.fillDefaults()
  				.grab(true, true).create());
  
  		Composite commitMessageToolbarComposite = toolkit
  				.createComposite(commitMessageSection);
  		commitMessageToolbarComposite.setBackground(null);
  		commitMessageToolbarComposite.setLayout(createRowLayoutWithoutMargin());
  		commitMessageSection.setTextClient(commitMessageToolbarComposite);
  		ToolBarManager commitMessageToolBarManager = new ToolBarManager(
  				SWT.FLAT | SWT.HORIZONTAL);
  
  		amendPreviousCommitAction = new Action(
  				UIText.StagingView_Ammend_Previous_Commit, IAction.AS_CHECK_BOX) {
  
  			@Override
  			public void run() {
  				commitMessageComponent.setAmendingButtonSelection(isChecked());
  				updateMessage();
  			}
  		};
  		amendPreviousCommitAction.setImageDescriptor(UIIcons.AMEND_COMMIT);
  		commitMessageToolBarManager.add(amendPreviousCommitAction);
  
  		signedOffByAction = new Action(UIText.StagingView_Add_Signed_Off_By,
  				IAction.AS_CHECK_BOX) {
  
  			@Override
  			public void run() {
  				commitMessageComponent.setSignedOffButtonSelection(isChecked());
  			}
  		};
  		signedOffByAction.setImageDescriptor(UIIcons.SIGNED_OFF);
  		commitMessageToolBarManager.add(signedOffByAction);
  
  		addChangeIdAction = new Action(UIText.StagingView_Add_Change_ID,
  				IAction.AS_CHECK_BOX) {
  
  			@Override
  			public void run() {
  				commitMessageComponent.setChangeIdButtonSelection(isChecked());
  			}
  		};
  		addChangeIdAction.setImageDescriptor(UIIcons.GERRIT);
  		commitMessageToolBarManager.add(addChangeIdAction);
  
  		commitMessageToolBarManager
  				.createControl(commitMessageToolbarComposite);
  
  		Composite commitMessageComposite = toolkit
  				.createComposite(commitMessageSection);
  		commitMessageSection.setClient(commitMessageComposite);
  		GridLayoutFactory.fillDefaults().numColumns(1)
  				.applyTo(commitMessageComposite);
  
  		warningLabel = new ToggleableWarningLabel(commitMessageComposite,
  				SWT.NONE);
  		GridDataFactory.fillDefaults().grab(true, false).exclude(true)
  				.applyTo(warningLabel);
  
  		Composite commitMessageTextComposite = toolkit
  				.createComposite(commitMessageComposite);
  		toolkit.paintBordersFor(commitMessageTextComposite);
  		GridDataFactory.fillDefaults().grab(true, true)
  				.applyTo(commitMessageTextComposite);
  		GridLayoutFactory.fillDefaults().numColumns(1)
  				.extendedMargins(2, 2, 2, 2)
  				.applyTo(commitMessageTextComposite);
  
  		final CommitProposalProcessor commitProposalProcessor = new CommitProposalProcessor() {
  			@Override
  			protected Collection<String> computeFileNameProposals() {
  				return getStagedFileNames();
  			}
  
  			@Override
  			protected Collection<String> computeMessageProposals() {
  				return CommitMessageHistory.getCommitHistory();
  			}
  		};
  		commitMessageText = new CommitMessageArea(commitMessageTextComposite,
  				EMPTY_STRING, toolkit.getBorderStyle()) {
  			@Override
  			protected CommitProposalProcessor getCommitProposalProcessor() {
  				return commitProposalProcessor;
  			}
  			@Override
  			protected IHandlerService getHandlerService() {
  				return CommonUtils.getService(getSite(), IHandlerService.class);
  			}
  		};
  		commitMessageText.setData(FormToolkit.KEY_DRAW_BORDER,
  				FormToolkit.TEXT_BORDER);
  		GridDataFactory.fillDefaults().grab(true, true)
  				.applyTo(commitMessageText);
  		UIUtils.addBulbDecorator(commitMessageText.getTextWidget(),
  				UIText.CommitDialog_ContentAssist);
  
  		Composite composite = toolkit.createComposite(commitMessageComposite);
  		toolkit.paintBordersFor(composite);
  		GridDataFactory.fillDefaults().grab(true, false).applyTo(composite);
  		GridLayoutFactory.swtDefaults().numColumns(2).applyTo(composite);
  
  		toolkit.createLabel(composite, UIText.StagingView_Author)
  				.setForeground(
  						toolkit.getColors().getColor(IFormColors.TB_TOGGLE));
  		authorText = toolkit.createText(composite, null);
  		authorText
  				.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TEXT_BORDER);
  		authorText.setLayoutData(GridDataFactory.fillDefaults()
  				.grab(true, false).create());
  
  		toolkit.createLabel(composite, UIText.StagingView_Committer)
  				.setForeground(
  						toolkit.getColors().getColor(IFormColors.TB_TOGGLE));
  		committerText = toolkit.createText(composite, null);
  		committerText.setData(FormToolkit.KEY_DRAW_BORDER,
  				FormToolkit.TEXT_BORDER);
  		committerText.setLayoutData(GridDataFactory.fillDefaults()
  				.grab(true, false).create());
  
  		Composite buttonsContainer = toolkit.createComposite(composite);
  		GridDataFactory.fillDefaults().grab(true, false).span(2, 1)
  				.indent(0, 8).applyTo(buttonsContainer);
  		GridLayoutFactory.fillDefaults().numColumns(2)
  				.applyTo(buttonsContainer);
  
  		Label filler = toolkit.createLabel(buttonsContainer, ""); //$NON-NLS-1$
  		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
  				.grab(true, true).applyTo(filler);
  
  		Composite commitButtonsContainer = toolkit
  				.createComposite(buttonsContainer);
  		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
  				.applyTo(commitButtonsContainer);
  		GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(true)
  				.applyTo(commitButtonsContainer);
  
  		this.commitAndPushButton = toolkit.createButton(commitButtonsContainer,
  				UIText.StagingView_CommitAndPush, SWT.PUSH);
  		commitAndPushButton.addSelectionListener(new SelectionAdapter() {
  			@Override
  			public void widgetSelected(SelectionEvent e) {
  				commit(true);
  			}
  		});
  		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
  				.applyTo(commitAndPushButton);
  
  		this.commitButton = toolkit.createButton(commitButtonsContainer,
  				UIText.StagingView_Commit, SWT.PUSH);
  		commitButton.setImage(getImage(UIIcons.COMMIT));
  		commitButton.setText(UIText.StagingView_Commit);
  		commitButton.addSelectionListener(new SelectionAdapter() {
  			@Override
  			public void widgetSelected(SelectionEvent e) {
  				commit(false);
  			}
  		});
  		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
  				.applyTo(commitButton);
  
  		stagedSection = toolkit.createSection(stagingSashForm,
  				ExpandableComposite.TITLE_BAR);
  
  		createStagedToolBarComposite();
  
  		Composite stagedComposite = toolkit.createComposite(stagedSection);
  		toolkit.paintBordersFor(stagedComposite);
  		stagedSection.setClient(stagedComposite);
  		GridLayoutFactory.fillDefaults().extendedMargins(2, 2, 2, 2)
  				.applyTo(stagedComposite);
  
  		stagedViewer = createTree(stagedComposite);
  		GridDataFactory.fillDefaults().grab(true, true)
  				.applyTo(stagedViewer.getControl());
  		stagedViewer.getTree().setData(FormToolkit.KEY_DRAW_BORDER,
  				FormToolkit.TREE_BORDER);
  		stagedViewer.setLabelProvider(createLabelProvider(stagedViewer));
  		stagedViewer.setContentProvider(createStagingContentProvider(false));
  		stagedViewer.addDragSupport(
  				DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK,
  				new Transfer[] { LocalSelectionTransfer.getTransfer(),
  						FileTransfer.getInstance() }, new StagingDragListener(
  						stagedViewer));
  		stagedViewer.addDropSupport(DND.DROP_MOVE,
  				new Transfer[] { LocalSelectionTransfer.getTransfer() },
  				new DropTargetAdapter() {
  					@Override
  					public void drop(DropTargetEvent event) {
  						// Bug 411466: It is very important that detail is set
  						// to DND.DROP_COPY. If it was left as DND.DROP_MOVE and
  						// the drag comes from the Navigator view, the code in
  						// NavigatorDragAdapter would delete the resources.
  						event.detail = DND.DROP_COPY;
  						if (event.data instanceof IStructuredSelection) {
  							final IStructuredSelection selection = (IStructuredSelection) event.data;
  							stage(selection);
  						}
  					}
  
  					@Override
  					public void dragOver(DropTargetEvent event) {
  						event.detail = DND.DROP_MOVE;
  					}
  				});
  		stagedViewer.addOpenListener(new IOpenListener() {
  			@Override
  			public void open(OpenEvent event) {
  				compareWith(event);
  			}
  		});
  		enableAutoExpand(stagedViewer);
  		addListenerToDisableAutoExpandOnCollapse(stagedViewer);
  
  		selectionChangedListener = new ISelectionListener() {
  			@Override
  			public void selectionChanged(IWorkbenchPart part,
  					ISelection selection) {
  				if (part == getSite().getPart()) {
  					return;
  				}
  				// don't accept text selection, only structural one
  				if (selection instanceof StructuredSelection) {
  					reactOnSelection((StructuredSelection) selection);
  				}
  			}
  		};
  
  		partListener = new PartListener();
  
  		IPreferenceStore preferenceStore = getPreferenceStore();
  		if (preferenceStore.contains(UIPreferences.STAGING_VIEW_SYNC_SELECTION))
  			reactOnSelection = preferenceStore.getBoolean(
  					UIPreferences.STAGING_VIEW_SYNC_SELECTION);
  		else
  			preferenceStore.setDefault(UIPreferences.STAGING_VIEW_SYNC_SELECTION, true);
  
  		InstanceScope.INSTANCE.getNode(
  				org.eclipse.egit.core.Activator.getPluginId())
  				.addPreferenceChangeListener(prefListener);
  
  		updateSectionText();
  		updateToolbar();
  		enableCommitWidgets(false);
  		refreshAction.setEnabled(false);
  
  		createPopupMenu(unstagedViewer);
  		createPopupMenu(stagedViewer);
  
  		final ICommitMessageComponentNotifications listener = new ICommitMessageComponentNotifications() {
  
  			@Override
  			public void updateSignedOffToggleSelection(boolean selection) {
  				signedOffByAction.setChecked(selection);
  			}
  
  			@Override
  			public void updateChangeIdToggleSelection(boolean selection) {
  				addChangeIdAction.setChecked(selection);
  			}
  
  			@Override
  			public void statusUpdated() {
  				updateMessage();
  			}
  		};
  		commitMessageComponent = new CommitMessageComponent(listener);
  		commitMessageComponent.attachControls(commitMessageText, authorText,
  				committerText);
  
  		// allow to commit with ctrl-enter
  		commitMessageText.getTextWidget().addVerifyKeyListener(new VerifyKeyListener() {
  			@Override
  			public void verifyKey(VerifyEvent event) {
  				if (UIUtils.isSubmitKeyEvent(event)) {
  					event.doit = false;
  					commit(false);
  				}
  			}
  		});
  
  		commitMessageText.getTextWidget().addFocusListener(new FocusListener() {
  			@Override
  			public void focusGained(FocusEvent e) {
  				// Ctrl+Enter shortcut only works when the focus is on the commit message text
  				String commitButtonTooltip = MessageFormat.format(
  						UIText.StagingView_CommitToolTip,
  						UIUtils.SUBMIT_KEY_STROKE.format());
  				commitButton.setToolTipText(commitButtonTooltip);
  			}
  
  			@Override
  			public void focusLost(FocusEvent e) {
  				commitButton.setToolTipText(null);
  			}
  		});
  
  		// react on selection changes
  		IWorkbenchPartSite site = getSite();
  		ISelectionService srv = CommonUtils.getService(site, ISelectionService.class);
  		srv.addPostSelectionListener(selectionChangedListener);
  		CommonUtils.getService(site, IPartService.class).addPartListener(
  				partListener);
  
  		// Use current selection to populate staging view
  		UIUtils.notifySelectionChangedWithCurrentSelection(
  				selectionChangedListener, site);
  
  		site.setSelectionProvider(unstagedViewer);
  
  		ViewerFilter filter = new ViewerFilter() {
  			@Override
  			public boolean select(Viewer viewer, Object parentElement,
  					Object element) {
  				StagingViewContentProvider contentProvider = getContentProvider((TreeViewer) viewer);
  				if (element instanceof StagingEntry)
  					return contentProvider.isInFilter((StagingEntry) element);
  				else if (element instanceof StagingFolderEntry)
  					return contentProvider
  							.hasVisibleChildren((StagingFolderEntry) element);
  				return true;
  			}
  		};
  		unstagedViewer.addFilter(filter);
  		stagedViewer.addFilter(filter);
  
  		IWorkbenchSiteProgressService service = CommonUtils.getService(
  				getSite(), IWorkbenchSiteProgressService.class);
  		if (service != null && reactOnSelection)
  			// If we are linked, each time IndexDiffUpdateJob starts, indicate
  			// that the view is busy (e.g. reload() will trigger this job in
  			// background!).
  			service.showBusyForFamily(org.eclipse.egit.core.JobFamilies.INDEX_DIFF_CACHE_UPDATE);
  	}
  
  	private void executeRebaseOperation(AbstractRebaseCommandHandler command) {
  		try {
  			command.execute(currentRepository);
  		} catch (ExecutionException e) {
  			Activator.showError(e.getMessage(), e);
  		}
  	}
  
  	/**
  	 * Abort rebase command in progress
  	 */
  	protected void rebaseAbort() {
  		AbortRebaseCommand abortCommand = new AbortRebaseCommand();
  		executeRebaseOperation(abortCommand);
  	}
  
  	/**
  	 * Rebase next commit and continue rebase in progress
  	 */
  	protected void rebaseSkip() {
  		SkipRebaseCommand skipCommand = new SkipRebaseCommand();
  		executeRebaseOperation(skipCommand);
  	}
  
  	/**
  	 * Continue rebase command in progress
  	 */
  	protected void rebaseContinue() {
  		ContinueRebaseCommand continueCommand = new ContinueRebaseCommand();
  		executeRebaseOperation(continueCommand);
  	}
  
  	private void createUnstagedToolBarComposite() {
  		Composite unstagedToolbarComposite = toolkit
  				.createComposite(unstagedSection);
  		unstagedToolbarComposite.setBackground(null);
  		unstagedToolbarComposite.setLayout(createRowLayoutWithoutMargin());
  		unstagedSection.setTextClient(unstagedToolbarComposite);
  		unstagedExpandAllAction = new Action(UIText.UIUtils_ExpandAll,
  				IAction.AS_PUSH_BUTTON) {
  			@Override
  			public void run() {
  				unstagedViewer.expandAll();
  				enableAutoExpand(unstagedViewer);
  			}
  		};
  		unstagedExpandAllAction.setImageDescriptor(UIIcons.EXPAND_ALL);
  
  		unstagedCollapseAllAction = new Action(UIText.UIUtils_CollapseAll,
  				IAction.AS_PUSH_BUTTON) {
  			@Override
  			public void run() {
  				unstagedViewer.collapseAll();
  				disableAutoExpand(unstagedViewer);
  			}
  		};
  		unstagedCollapseAllAction.setImageDescriptor(UIIcons.COLLAPSEALL);
  
  		unstagedToolBarManager = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL);
  
  		unstagedToolBarManager.add(unstagedExpandAllAction);
  		unstagedToolBarManager.add(unstagedCollapseAllAction);
  
  		unstagedToolBarManager.update(true);
  		unstagedToolBarManager.createControl(unstagedToolbarComposite);
  	}
  
  	private void createStagedToolBarComposite() {
  		Composite stagedToolbarComposite = toolkit
  				.createComposite(stagedSection);
  		stagedToolbarComposite.setBackground(null);
  		stagedToolbarComposite.setLayout(createRowLayoutWithoutMargin());
  		stagedSection.setTextClient(stagedToolbarComposite);
  		stagedExpandAllAction = new Action(UIText.UIUtils_ExpandAll,
  				IAction.AS_PUSH_BUTTON) {
  			@Override
  			public void run() {
  				stagedViewer.expandAll();
  				enableAutoExpand(stagedViewer);
  			}
  		};
  		stagedExpandAllAction.setImageDescriptor(UIIcons.EXPAND_ALL);
  
  		stagedCollapseAllAction = new Action(UIText.UIUtils_CollapseAll,
  				IAction.AS_PUSH_BUTTON) {
  			@Override
  			public void run() {
  				stagedViewer.collapseAll();
  				disableAutoExpand(stagedViewer);
  			}
  		};
  		stagedCollapseAllAction.setImageDescriptor(UIIcons.COLLAPSEALL);
  
  		stagedToolBarManager = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL);
  
  		stagedToolBarManager.add(stagedExpandAllAction);
  		stagedToolBarManager.add(stagedCollapseAllAction);
  		stagedToolBarManager.update(true);
  		stagedToolBarManager.createControl(stagedToolbarComposite);
  	}
  
  	private static RowLayout createRowLayoutWithoutMargin() {
  		RowLayout layout = new RowLayout();
  		layout.marginHeight = 0;
  		layout.marginWidth = 0;
  		layout.marginTop = 0;
  		layout.marginBottom = 0;
  		layout.marginLeft = 0;
  		layout.marginRight = 0;
  		return layout;
  	}
  
  	private static void addListenerToDisableAutoExpandOnCollapse(
  			TreeViewer treeViewer) {
  		treeViewer.addTreeListener(new ITreeViewerListener() {
  			@Override
  			public void treeCollapsed(TreeExpansionEvent event) {
  				disableAutoExpand(event.getTreeViewer());
  			}
  
  			@Override
  			public void treeExpanded(TreeExpansionEvent event) {
  				// Nothing to do
  			}
  		});
  	}
  
  	private static void enableAutoExpand(AbstractTreeViewer treeViewer) {
  		treeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
  	}
  
  	private static void disableAutoExpand(AbstractTreeViewer treeViewer) {
  		treeViewer.setAutoExpandLevel(0);
  	}
  
  	/**
  	 * @return selected repository
  	 */
  	public Repository getCurrentRepository() {
  		return currentRepository;
  	}
  
  	@Override
  	public ShowInContext getShowInContext() {
  		if (stagedViewer != null && stagedViewer.getTree().isFocusControl())
  			return getShowInContext(stagedViewer);
  