org.eclipse.egit.ui.internal.sharing.ExistingOrNewPage.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.egit.ui.internal.sharing.ExistingOrNewPage.java

Source

/*******************************************************************************
 * Copyright (C) 2009, Robin Rosenberg
 * Copyright (C) 2009, Mykola Nikishov <mn@mn.com.ua>
 *
 * 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.sharing;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.egit.core.RepositoryUtil;
import org.eclipse.egit.core.project.RepositoryFinder;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIIcons;
import org.eclipse.egit.ui.UIText;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;

/**
 * Wizard page for connecting projects to Git repositories.
 */
class ExistingOrNewPage extends WizardPage {

    private final SharingWizard myWizard;
    private Button button;
    private Tree tree;
    private CheckboxTreeViewer viewer;
    private Text repositoryToCreate;
    private IPath minumumPath;
    private Text dotGitSegment;

    ExistingOrNewPage(SharingWizard w) {
        super(ExistingOrNewPage.class.getName());
        setTitle(UIText.ExistingOrNewPage_title);
        setDescription(UIText.ExistingOrNewPage_description);
        setImageDescriptor(UIIcons.WIZBAN_CONNECT_REPO);
        this.myWizard = w;
    }

    public void createControl(Composite parent) {
        Group g = new Group(parent, SWT.NONE);
        g.setLayout(new GridLayout(3, false));
        g.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
        tree = new Tree(g, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION | SWT.CHECK);
        viewer = new CheckboxTreeViewer(tree);
        tree.setHeaderVisible(true);
        tree.setLayout(new GridLayout());
        tree.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).span(3, 1).create());
        viewer.addCheckStateListener(new ICheckStateListener() {

            public void checkStateChanged(CheckStateChangedEvent event) {
                if (event.getChecked()) {
                    ProjectAndRepo checkable = (ProjectAndRepo) event.getElement();
                    for (TreeItem ti : tree.getItems()) {
                        if (ti.getItemCount() > 0 || ((ProjectAndRepo) ti.getData()).getRepo().equals("")) //$NON-NLS-1$
                            ti.setChecked(false);
                        for (TreeItem subTi : ti.getItems()) {
                            IProject project = ((ProjectAndRepo) subTi.getData()).getProject();
                            if (checkable.getProject() != null && !subTi.getData().equals(checkable)
                                    && checkable.getProject().equals(project))
                                subTi.setChecked(false);
                        }
                    }
                }
            }
        });
        TreeColumn c1 = new TreeColumn(tree, SWT.NONE);
        c1.setText(UIText.ExistingOrNewPage_HeaderProject);
        c1.setWidth(100);
        TreeColumn c2 = new TreeColumn(tree, SWT.NONE);
        c2.setText(UIText.ExistingOrNewPage_HeaderPath);
        c2.setWidth(400);
        TreeColumn c3 = new TreeColumn(tree, SWT.NONE);
        c3.setText(UIText.ExistingOrNewPage_HeaderRepository);
        c3.setWidth(200);
        for (IProject project : myWizard.projects) {
            RepositoryFinder repositoryFinder = new RepositoryFinder(project);
            try {
                Collection<RepositoryMapping> mappings;
                mappings = repositoryFinder.find(new NullProgressMonitor());
                Iterator<RepositoryMapping> mi = mappings.iterator();
                RepositoryMapping m = mi.hasNext() ? mi.next() : null;
                if (m == null) {
                    // no mapping found, enable repository creation
                    TreeItem treeItem = new TreeItem(tree, SWT.NONE);
                    treeItem.setText(0, project.getName());
                    treeItem.setText(1, project.getLocation().toOSString());
                    treeItem.setText(2, ""); //$NON-NLS-1$
                    treeItem.setData(new ProjectAndRepo(project, "")); //$NON-NLS-1$
                } else if (!mi.hasNext()) {
                    // exactly one mapping found
                    TreeItem treeItem = new TreeItem(tree, SWT.NONE);
                    treeItem.setText(0, project.getName());
                    treeItem.setText(1, project.getLocation().toOSString());
                    fillTreeItemWithGitDirectory(m, treeItem, false);
                    treeItem.setData(new ProjectAndRepo(project, treeItem.getText(2)));
                    treeItem.setChecked(true);
                }

                else {
                    TreeItem treeItem = new TreeItem(tree, SWT.NONE);
                    treeItem.setText(0, project.getName());
                    treeItem.setText(1, project.getLocation().toOSString());
                    treeItem.setData(new ProjectAndRepo(null, null));

                    TreeItem treeItem2 = new TreeItem(treeItem, SWT.NONE);
                    treeItem2.setText(0, project.getName());
                    fillTreeItemWithGitDirectory(m, treeItem2, true);
                    treeItem2.setData(new ProjectAndRepo(project, treeItem2.getText(2)));
                    while (mi.hasNext()) { // fill in additional mappings
                        m = mi.next();
                        treeItem2 = new TreeItem(treeItem, SWT.NONE);
                        treeItem2.setText(0, project.getName());
                        fillTreeItemWithGitDirectory(m, treeItem2, true);
                        treeItem2.setData(new ProjectAndRepo(m.getContainer().getProject(), treeItem2.getText(2)));
                    }
                    treeItem.setExpanded(true);
                }
            } catch (CoreException e) {
                TreeItem treeItem2 = new TreeItem(tree, SWT.BOLD | SWT.ITALIC);
                treeItem2.setText(e.getMessage());
            }
        }

        button = new Button(g, SWT.PUSH);
        button.setLayoutData(GridDataFactory.fillDefaults().create());
        button.setText(UIText.ExistingOrNewPage_CreateButton);
        button.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                File gitDir = new File(repositoryToCreate.getText(), Constants.DOT_GIT);
                try {
                    Repository repository = new FileRepository(gitDir);
                    repository.create();
                    for (IProject project : getProjects().keySet()) {
                        // If we don't refresh the project directories right
                        // now we won't later know that a .git directory
                        // exists within it and we won't mark the .git
                        // directory as a team-private member. Failure
                        // to do so might allow someone to delete
                        // the .git directory without us stopping them.
                        // (Half lie, we should optimize so we do not
                        // refresh when the .git is not within the project)
                        //
                        if (!gitDir.toString().contains("..")) //$NON-NLS-1$
                            project.refreshLocal(IResource.DEPTH_ONE, new NullProgressMonitor());
                    }
                    RepositoryUtil util = Activator.getDefault().getRepositoryUtil();
                    util.addConfiguredRepository(gitDir);
                } catch (IOException e1) {
                    String msg = NLS.bind(UIText.ExistingOrNewPage_ErrorFailedToCreateRepository,
                            gitDir.toString());
                    org.eclipse.egit.ui.Activator.handleError(msg, e1, true);
                } catch (CoreException e2) {
                    String msg = NLS.bind(UIText.ExistingOrNewPage_ErrorFailedToRefreshRepository, gitDir);
                    org.eclipse.egit.ui.Activator.handleError(msg, e2, true);
                }
                for (TreeItem ti : tree.getSelection()) {
                    ti.setText(2, gitDir.toString());
                    ((ProjectAndRepo) ti.getData()).repo = gitDir.toString();
                    ti.setChecked(true);
                }
                updateCreateOptions();
                getContainer().updateButtons();
            }
        });
        repositoryToCreate = new Text(g, SWT.SINGLE | SWT.BORDER);
        repositoryToCreate.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).span(1, 1).create());
        repositoryToCreate.addListener(SWT.Modify, new Listener() {
            public void handleEvent(Event e) {
                if (repositoryToCreate.getText().equals("")) { //$NON-NLS-1$
                    button.setEnabled(false);
                    return;
                }
                IPath fromOSString = Path.fromOSString(repositoryToCreate.getText());
                button.setEnabled(minumumPath.matchingFirstSegments(fromOSString) == fromOSString.segmentCount());
            }
        });
        dotGitSegment = new Text(g, SWT.NONE);
        dotGitSegment.setEnabled(false);
        dotGitSegment.setEditable(false);
        dotGitSegment.setText(File.separatorChar + Constants.DOT_GIT);
        dotGitSegment.setLayoutData(GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.CENTER).create());

        tree.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                updateCreateOptions();
            }
        });
        updateCreateOptions();
        Dialog.applyDialogFont(g);
        setControl(g);
    }

    private void fillTreeItemWithGitDirectory(RepositoryMapping m, TreeItem treeItem2, boolean isAlternative) {
        if (m.getGitDir() == null)
            treeItem2.setText(2, UIText.ExistingOrNewPage_SymbolicValueEmptyMapping);
        else {
            IPath container = m.getContainerPath();
            if (!container.isEmpty())
                container = container.addTrailingSeparator();
            IPath relativePath = container.append(m.getGitDir());
            if (isAlternative)
                treeItem2.setText(0, relativePath.removeLastSegments(1).addTrailingSeparator().toString());
            treeItem2.setText(2, relativePath.toString());
        }
    }

    private void updateCreateOptions() {
        minumumPath = null;
        IPath p = null;
        for (TreeItem ti : tree.getSelection()) {
            if (ti.getItemCount() > 0)
                continue;
            String path = ti.getText(2);
            if (!path.equals("")) { //$NON-NLS-1$
                p = null;
                break;
            }
            String gitDirParentCandidate = ti.getText(1);
            IPath thisPath = Path.fromOSString(gitDirParentCandidate);
            if (p == null)
                p = thisPath;
            else {
                int n = p.matchingFirstSegments(thisPath);
                p = p.removeLastSegments(p.segmentCount() - n);
            }
        }
        minumumPath = p;
        if (p != null) {
            repositoryToCreate.setText(p.toOSString());
        } else {
            repositoryToCreate.setText(""); //$NON-NLS-1$
        }
        button.setEnabled(p != null);
        repositoryToCreate.setEnabled(p != null);
        dotGitSegment.setEnabled(p != null);
        getContainer().updateButtons();
    }

    @Override
    public boolean isPageComplete() {
        if (viewer.getCheckedElements().length == 0)
            return false;
        for (Object checkedElement : viewer.getCheckedElements()) {
            String path = ((ProjectAndRepo) checkedElement).getRepo();
            if (((ProjectAndRepo) checkedElement).getRepo() != null && path.equals("")) { //$NON-NLS-1$
                return false;
            }
        }
        return true;
    }

    /**
     * @return map between project and repository root directory (converted to an
     *         absolute path) for all projects selected by user
     */
    public Map<IProject, File> getProjects() {
        final Object[] checkedElements = viewer.getCheckedElements();
        Map<IProject, File> ret = new HashMap<IProject, File>(checkedElements.length);
        for (Object ti : viewer.getCheckedElements()) {
            final IProject project = ((ProjectAndRepo) ti).getProject();
            String path = ((ProjectAndRepo) ti).getRepo();
            final IPath selectedRepo = Path.fromOSString(path);
            IPath localPathToRepo = selectedRepo;
            if (!selectedRepo.isAbsolute()) {
                localPathToRepo = project.getLocation().append(selectedRepo);
            }
            ret.put(project, localPathToRepo.toFile());
        }
        return ret;
    }

    private static class ProjectAndRepo {
        private IProject project;
        private String repo;

        public ProjectAndRepo(IProject project, String repo) {
            this.project = project;
            this.repo = repo;
        }

        public IProject getProject() {
            return project;
        }

        public String getRepo() {
            return repo;
        }
    }
}