blob: 69af9201d4530cf91958dd308bb02d11de55cc87 [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2011, 2012 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:
* Mathias Kinzler (SAP AG) - initial implementation
* Benjamin Muskalla <bmuskalla@eclipsesource.com>
* Daniel Megert <daniel_megert@ch.ibm.com> - remove unnecessary @SuppressWarnings
*******************************************************************************/
package org.eclipse.egit.ui.internal.clone;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.egit.core.RepositoryUtil;
import org.eclipse.egit.core.internal.gerrit.GerritUtil;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.egit.ui.internal.repository.RepositoriesViewContentProvider;
import org.eclipse.egit.ui.internal.repository.RepositoriesViewLabelProvider;
import org.eclipse.egit.ui.internal.repository.RepositorySearchWizard;
import org.eclipse.egit.ui.internal.repository.tree.RepositoryNode;
import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
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.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;
/**
* Select a repository, add or clone
*/
public class GitSelectRepositoryPage extends WizardPage {
private final static String LAST_SELECTED_REPO_PREF = "GitSelectRepositoryPage.lastRepository"; //$NON-NLS-1$
private final RepositoryUtil util;
private final boolean allowBare;
private TreeViewer tv;
private Button addRepo;
private Composite bareMsg;
private IPreferenceChangeListener configChangeListener;
/**
* Creates a new {@link GitSelectRepositoryPage} that allows also bare
* repositories to be selected.
*/
public GitSelectRepositoryPage() {
this(true);
}
/**
* Creates a new {@link GitSelectRepositoryPage}.
*
* @param allowBare
* whether bare repositories shall be shown
*/
public GitSelectRepositoryPage(boolean allowBare) {
super(GitSelectRepositoryPage.class.getName());
setTitle(UIText.GitSelectRepositoryPage_PageTitle);
setDescription(UIText.GitSelectRepositoryPage_PageMessage);
util = Activator.getDefault().getRepositoryUtil();
this.allowBare = allowBare;
}
/**
* @return the repository
*/
public Repository getRepository() {
Object obj = ((IStructuredSelection) tv.getSelection())
.getFirstElement();
if (obj == null)
return null;
return ((RepositoryTreeNode) obj).getRepository();
}
@Override
public void createControl(Composite parent) {
Composite main = new Composite(parent, SWT.NONE);
GridLayoutFactory.fillDefaults().numColumns(2).margins(0, 0).applyTo(
main);
GridDataFactory.fillDefaults().grab(true, true).applyTo(main);
// use a filtered tree
FilteredTree tree = new FilteredTree(main, SWT.SINGLE | SWT.BORDER
| SWT.H_SCROLL | SWT.V_SCROLL, new PatternFilter(), true);
tv = tree.getViewer();
GridDataFactory.fillDefaults().grab(true, true).applyTo(tree);
tv.setContentProvider(new RepositoriesViewContentProvider() {
@Override
public Object[] getElements(Object inputElement) {
Object[] elements = super.getElements(inputElement);
if (allowBare) {
return elements;
}
List<Object> result = new ArrayList<>();
for (Object element : elements) {
if (element instanceof RepositoryTreeNode) {
RepositoryTreeNode node = (RepositoryTreeNode) element;
if (node.getRepository() != null
&& !node.getRepository().isBare()) {
result.add(element);
}
}
}
bareMsg.setVisible(result.size() != elements.length);
return result.toArray();
}
// we never show children, only the Repository nodes
@Override
public Object[] getChildren(Object parentElement) {
return null;
}
@Override
public boolean hasChildren(Object element) {
return false;
}
});
tv.setLabelProvider(new RepositoriesViewLabelProvider());
Composite tb = new Composite(main, SWT.NONE);
GridLayoutFactory.fillDefaults().numColumns(1).applyTo(tb);
GridDataFactory.fillDefaults().grab(false, true).applyTo(tb);
addRepo = new Button(tb, SWT.PUSH);
GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL,
SWT.BEGINNING).applyTo(addRepo);
addRepo.setText(UIText.GitSelectRepositoryPage_AddButton);
addRepo.setToolTipText(UIText.GitSelectRepositoryPage_AddTooltip);
addRepo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
List<String> configuredDirs = util.getConfiguredRepositories();
RepositorySearchWizard wizard = new RepositorySearchWizard(
configuredDirs, allowBare);
WizardDialog dlg = new WizardDialog(getShell(), wizard);
if (dlg.open() == Window.OK
&& !wizard.getDirectories().isEmpty()) {
Set<String> dirs = wizard.getDirectories();
for (String dir : dirs) {
File gitDir = FileUtils.canonicalize(new File(dir));
GerritUtil.tryToAutoConfigureForGerrit(gitDir);
util.addConfiguredRepository(gitDir);
}
checkPage();
}
}
});
if (!allowBare) {
bareMsg = new Composite(main, SWT.NONE);
bareMsg.setLayout(new RowLayout());
bareMsg.setLayoutData(
GridDataFactory.fillDefaults().grab(true, false).create());
Label imageLabel = new Label(bareMsg, SWT.NONE);
imageLabel.setImage(
JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_INFO));
Label textLabel = new Label(bareMsg, SWT.WRAP);
textLabel.setText(
UIText.GitSelectRepositoryPage_BareRepositoriesHidden);
bareMsg.setVisible(false);
}
tv.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
checkPage();
}
});
tv.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
checkPage();
if (isPageComplete())
getContainer().showPage(getNextPage());
}
});
tv.setInput(util.getConfiguredRepositories());
configChangeListener = new IPreferenceChangeListener() {
@Override
public void preferenceChange(PreferenceChangeEvent event) {
Display display = tv.getControl().getDisplay();
display.asyncExec(new Runnable() {
@Override
public void run() {
if (!tv.getControl().isDisposed()) {
refreshRepositoryList();
checkPage();
}
}
});
}
};
util.getPreferences().addPreferenceChangeListener(configChangeListener);
// we need to select at least a repository to become complete
setPageComplete(false);
Dialog.applyDialogFont(main);
setControl(main);
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
IDialogSettings settings = Activator.getDefault().getDialogSettings();
if (visible && tv.getSelection().isEmpty()) {
// check in the dialog settings if a repository was selected before
// and select it if nothing else is selected
String repoDir = settings.get(LAST_SELECTED_REPO_PREF);
if (repoDir != null)
for (TreeItem item : tv.getTree().getItems()) {
RepositoryNode node = (RepositoryNode) item.getData();
if (node.getRepository().getDirectory().getPath().equals(
repoDir))
tv.setSelection(new StructuredSelection(node));
}
} else {
// save selection in dialog settings
Object element = ((IStructuredSelection) tv.getSelection())
.getFirstElement();
if (element instanceof RepositoryNode)
settings.put(LAST_SELECTED_REPO_PREF,
((RepositoryNode) element).getRepository()
.getDirectory().getPath());
}
}
private void refreshRepositoryList() {
List<?> dirsBefore = (List<?>) tv.getInput();
List<String> dirsAfter = util.getConfiguredRepositories();
if (dirsBefore == null) {
dirsBefore = Collections.emptyList();
}
if (!dirsBefore.containsAll(dirsAfter)) {
IStructuredSelection previousSelection = (IStructuredSelection) tv
.getSelection();
tv.setInput(dirsAfter);
for (String dir : dirsAfter) {
if (!dirsBefore.contains(dir)) {
try {
Repository newRepository = org.eclipse.egit.core.Activator
.getDefault().getRepositoryCache()
.lookupRepository(new File(dir));
if (!allowBare && newRepository.isBare()) {
// Re-set to previous selection, if any
if (!previousSelection.isEmpty()) {
tv.setSelection(previousSelection);
}
} else {
RepositoryNode node = new RepositoryNode(null,
newRepository);
tv.setSelection(new StructuredSelection(node));
}
} catch (IOException e1) {
Activator.handleError(e1.getMessage(), e1,
false);
}
break;
}
}
}
}
private void checkPage() {
setErrorMessage(null);
try {
List<?> currentInput = (List<?>) tv.getInput();
if (currentInput == null || currentInput.isEmpty()) {
setErrorMessage(UIText.GitSelectRepositoryPage_NoRepoFoundMessage);
return;
}
if (tv.getSelection().isEmpty()) {
setErrorMessage(UIText.GitSelectRepositoryPage_PleaseSelectMessage);
return;
}
} finally {
setPageComplete(getErrorMessage() == null);
}
}
@Override
public void dispose() {
super.dispose();
util.getPreferences().removePreferenceChangeListener(
configChangeListener);
}
}