From a29fc6296deb5c618d4d77b8eda347e8bb2aa4cf Mon Sep 17 00:00:00 2001 From: Mathias Kinzler Date: Mon, 3 May 2010 12:39:56 +0200 Subject: [PATCH] Git Repositories View: Import Projects Add some context menu in the view to allow starting of different wizards for project import (not only the Import Existing Projects wizard). This is also in preparation for a better Git Import wizard. The bug below is not solved by this, but this should help in the discussion of it. Bug: 281394 Change-Id: Ic673e8119158adfbf7147ac3ce925bd7f37fa9e4 Signed-off-by: Mathias Kinzler Signed-off-by: Chris Aniszczyk --- .../src/org/eclipse/egit/ui/UIText.java | 87 ++++++ .../clone/GitCreateGeneralProjectPage.java | 186 ++++++++++++ .../clone/GitCreateProjectViaWizardWizard.java | 313 +++++++++++++++++++++ .../ui/internal/clone/GitProjectsImportPage.java | 35 ++- .../ui/internal/clone/GitSelectWizardPage.java | 212 ++++++++++++++ .../ui/internal/clone/GitShareProjectsPage.java | 246 ++++++++++++++++ .../ui/internal/repository/RepositoriesView.java | 102 +++++-- .../src/org/eclipse/egit/ui/uitext.properties | 29 ++ 8 files changed, 1179 insertions(+), 31 deletions(-) create mode 100644 org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitCreateGeneralProjectPage.java create mode 100644 org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitCreateProjectViaWizardWizard.java create mode 100644 org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectWizardPage.java create mode 100644 org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitShareProjectsPage.java diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java index 7e7f972f..be35f96e 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java @@ -1534,6 +1534,9 @@ public class UIText extends NLS { public static String RepositoriesView_ConfirmProjectDeletion_WindowTitle; /** */ + public static String RepositoriesView_CopyPathToClipboardMenu; + + /** */ public static String RepositoriesView_CreateFetch_menu; /** */ @@ -1558,6 +1561,9 @@ public class UIText extends NLS { public static String RepositoriesView_ImportProject_MenuItem; /** */ + public static String RepositoriesView_ImportProjectsMenu; + + /** */ public static String RepositoriesView_ImportRepository_MenuItem; /** */ @@ -1633,6 +1639,87 @@ public class UIText extends NLS { public static String GitCompareFileRevisionEditorInput_contentIdentifier; /** */ + public static String GitCreateGeneralProjectPage_DirLabel; + + /** */ + public static String GitCreateGeneralProjectPage_DirNotExistMessage; + + /** */ + public static String GitCreateGeneralProjectPage_EnterProjectNameMessage; + + /** */ + public static String GitCreateGeneralProjectPage_FileExistsInDirMessage; + + /** */ + public static String GitCreateGeneralProjectPage_FileNotDirMessage; + + /** */ + public static String GitCreateGeneralProjectPage_PorjectAlreadyExistsMessage; + + /** */ + public static String GitCreateGeneralProjectPage_ProjectNameLabel; + + /** */ + public static String GitCreateProjectViaWizardWizard_AbortedMessage; + + /** */ + public static String GitCreateProjectViaWizardWizard_WizardTitle; + + /** */ + public static String GitSelectWizardPage_AutoShareButton; + + /** */ + public static String GitSelectWizardPage_ImportAsGeneralButton; + + /** */ + public static String GitSelectWizardPage_ImportExistingButton; + + /** */ + public static String GitSelectWizardPage_InteractiveShareButton; + + /** */ + public static String GitSelectWizardPage_NoShareButton; + + /** */ + public static String GitSelectWizardPage_ProjectCreationHeader; + + /** */ + public static String GitSelectWizardPage_SharingProjectsHeader; + + /** */ + public static String GitSelectWizardPage_UseNewProjectsWizardButton; + + /** */ + public static String GitSelectWizardPage_WizardTitle; + + /** */ + public static String GitShareProjectsPage_AbortedMessage; + + /** */ + public static String GitShareProjectsPage_NoNewProjectMessage; + + /** */ + public static String GitShareProjectsPage_NoRepoForProjectMessage; + + /** */ + public static String GitShareProjectsPage_NoRepoFoundMessage; + + /** */ + public static String GitShareProjectsPage_NothingSelectedMessage; + + /** */ + public static String GitShareProjectsPage_PageTitle; + + /** */ + public static String GitShareProjectsPage_ProjectAlreadySharedMessage; + + /** */ + public static String GitShareProjectsPage_ProjectNameLabel; + + /** */ + public static String GitShareProjectsPage_RepositoryLabel; + + /** */ public static String UIIcons_errorDeterminingIconBase; /** */ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitCreateGeneralProjectPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitCreateGeneralProjectPage.java new file mode 100644 index 00000000..9282ac93 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitCreateGeneralProjectPage.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2010 SAP AG. + * 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 + *******************************************************************************/ +package org.eclipse.egit.ui.internal.clone; + +import java.io.File; +import java.io.FilenameFilter; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.egit.ui.UIText; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * Allows to import a directory in the local file system as "General" project + *

+ * Asks the user to provide a project name and shows the directory to be shared. + *

+ * TODO String externalization + */ +public class GitCreateGeneralProjectPage extends WizardPage { + + private final File myDirectory; + + private Text projectText; + + private Text directoryText; + + private IProject[] wsProjects; + + /** + * Creates a new project creation wizard page. + * + * @param path + * the path to a directory in the local file system + */ + public GitCreateGeneralProjectPage(String path) { + super(GitCreateGeneralProjectPage.class.getName()); + myDirectory = new File(path); + setPageComplete(false); + setTitle(UIText.WizardProjectsImportPage_ImportProjectsTitle); + setDescription(UIText.WizardProjectsImportPage_ImportProjectsDescription); + } + + public void createControl(Composite parent) { + + initializeDialogUnits(parent); + + Composite workArea = new Composite(parent, SWT.NONE); + setControl(workArea); + + workArea.setLayout(new GridLayout(2, false)); + workArea.setLayoutData(new GridData(GridData.FILL_BOTH + | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL)); + + new Label(workArea, SWT.NONE).setText(UIText.GitCreateGeneralProjectPage_ProjectNameLabel); + projectText = new Text(workArea, SWT.BORDER); + GridDataFactory.fillDefaults().grab(true, false).applyTo(projectText); + projectText.addModifyListener(new ModifyListener() { + + public void modifyText(ModifyEvent e) { + checkPage(); + } + }); + + new Label(workArea, SWT.NONE).setText(UIText.GitCreateGeneralProjectPage_DirLabel); + directoryText = new Text(workArea, SWT.BORDER); + directoryText.setEnabled(false); + GridDataFactory.fillDefaults().grab(true, false).applyTo(directoryText); + + Dialog.applyDialogFont(workArea); + + } + + @Override + public void setVisible(boolean visible) { + if (visible) { + projectText.setText(myDirectory.getName()); + directoryText.setText(myDirectory.getPath()); + checkPage(); + } + super.setVisible(visible); + } + + /** + * @return the project name + */ + public String getProjectName() { + return projectText.getText(); + } + + private void checkPage() { + String projectName = projectText.getText(); + setErrorMessage(null); + try { + // make sure the directory exists + if (!myDirectory.exists()) { + setErrorMessage(NLS.bind(UIText.GitCreateGeneralProjectPage_DirNotExistMessage, + myDirectory.getPath())); + return; + } + // make sure we don't have a file + if (!myDirectory.isDirectory()) { + setErrorMessage(NLS.bind(UIText.GitCreateGeneralProjectPage_FileNotDirMessage, + myDirectory.getPath())); + return; + } + // make sure there is not already a .project file + if (myDirectory.list(new FilenameFilter() { + + public boolean accept(File dir, String name) { + if (name.equals(".project")) //$NON-NLS-1$ + return true; + return false; + } + }).length > 0) { + setErrorMessage(NLS.bind( + UIText.GitCreateGeneralProjectPage_FileExistsInDirMessage, + ".project", myDirectory.getPath())); //$NON-NLS-1$ + return; + } + // project name empty + if (projectName.length() == 0) { + setErrorMessage(UIText.GitCreateGeneralProjectPage_EnterProjectNameMessage); + return; + } + // project name valid (no strange chars...) + IStatus result = ResourcesPlugin.getWorkspace().validateName( + projectName, IResource.PROJECT); + if (!result.isOK()) { + setErrorMessage(result.getMessage()); + return; + } + // project already exists + if (isProjectInWorkspace(projectName)) { + setErrorMessage(NLS.bind(UIText.GitCreateGeneralProjectPage_PorjectAlreadyExistsMessage, + projectName)); + return; + } + } finally { + setPageComplete(getErrorMessage() == null); + } + + } + + private IProject[] getProjectsInWorkspace() { + if (wsProjects == null) { + wsProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); + } + return wsProjects; + } + + private boolean isProjectInWorkspace(String projectName) { + if (projectName == null) { + return false; + } + IProject[] workspaceProjects = getProjectsInWorkspace(); + for (int i = 0; i < workspaceProjects.length; i++) { + if (projectName.equals(workspaceProjects[i].getName())) { + return true; + } + } + return false; + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitCreateProjectViaWizardWizard.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitCreateProjectViaWizardWizard.java new file mode 100644 index 00000000..ece7e60f --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitCreateProjectViaWizardWizard.java @@ -0,0 +1,313 @@ +/******************************************************************************* + * Copyright (c) 2010 SAP AG. + * 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 + *******************************************************************************/ +package org.eclipse.egit.ui.internal.clone; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.Path; +import org.eclipse.egit.core.op.ConnectProviderOperation; +import org.eclipse.egit.ui.Activator; +import org.eclipse.egit.ui.UIText; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.widgets.Display; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.actions.NewWizardAction; +import org.eclipse.ui.actions.WorkspaceModifyOperation; + +/** + * A wizard used to import existing projects from a {@link Repository} + */ +public class GitCreateProjectViaWizardWizard extends Wizard { + + private final Repository myRepository; + + private final String myGitDir; + + private final IProject[] previousProjects; + + private GitSelectWizardPage mySelectionPage; + + private GitCreateGeneralProjectPage myCreateGeneralProjectPage; + + private GitProjectsImportPage myProjectsImportPage; + + private GitShareProjectsPage mySharePage; + + /** + * @param repository + * @param path + */ + public GitCreateProjectViaWizardWizard(Repository repository, String path) { + super(); + previousProjects = ResourcesPlugin.getWorkspace().getRoot() + .getProjects(); + myRepository = repository; + myGitDir = path; + setWindowTitle(NLS.bind( + UIText.GitCreateProjectViaWizardWizard_WizardTitle, + myRepository.getDirectory().getPath())); + + // the "Import" wizard could be started like this, + // but throws an Exception if started within a wizard + // context (no active workbench window found) and the + // list of available wizards is empty + // -> investigate if we can include that wizard + // + // IHandlerService handlerService = (IHandlerService) + // PlatformUI.getWorkbench().getService(IHandlerService.class); + // + // handlerService.executeCommand("org.eclipse.ui.file.import", + + } + + @Override + public void addPages() { + + mySelectionPage = new GitSelectWizardPage(); + addPage(mySelectionPage); + myCreateGeneralProjectPage = new GitCreateGeneralProjectPage(myGitDir); + addPage(myCreateGeneralProjectPage); + // for "Import Existing Projects" + // TODO new constructor with repository and directory once we + // remove this page from the GitCloneWizard + myProjectsImportPage = new GitProjectsImportPage(false) { + + @Override + public void setVisible(boolean visible) { + setGitDir(myRepository.getDirectory()); + setProjectsList(myGitDir); + super.setVisible(visible); + } + + }; + addPage(myProjectsImportPage); + mySharePage = new GitShareProjectsPage(); + addPage(mySharePage); + } + + @Override + public IWizardPage getNextPage(IWizardPage page) { + + if (page == mySelectionPage) { + + switch (mySelectionPage.getWizardSelection()) { + case GitSelectWizardPage.EXISTING_PROJECTS_WIZARD: + return myProjectsImportPage; + case GitSelectWizardPage.NEW_WIZARD: + if (mySelectionPage.getActionSelection() != GitSelectWizardPage.ACTION_DIALOG_SHARE) + return null; + else + return mySharePage; + + case GitSelectWizardPage.GENERAL_WIZARD: + return myCreateGeneralProjectPage; + + } + + return super.getNextPage(page); + + } else if (page == myCreateGeneralProjectPage + || page == myProjectsImportPage) { + + if (mySelectionPage.getActionSelection() != GitSelectWizardPage.ACTION_DIALOG_SHARE) + return null; + else + return mySharePage; + } + return super.getNextPage(page); + } + + @Override + public boolean canFinish() { + + boolean showSharePage = mySelectionPage.getActionSelection() == GitSelectWizardPage.ACTION_DIALOG_SHARE; + boolean showShareComplete = !showSharePage + || mySharePage.isPageComplete(); + + switch (mySelectionPage.getWizardSelection()) { + case GitSelectWizardPage.EXISTING_PROJECTS_WIZARD: + return myProjectsImportPage.isPageComplete() && showShareComplete; + case GitSelectWizardPage.NEW_WIZARD: + return showShareComplete; + case GitSelectWizardPage.GENERAL_WIZARD: + return myCreateGeneralProjectPage.isPageComplete() + && showShareComplete; + } + return super.canFinish(); + + } + + @Override + public boolean performFinish() { + + try { + + final int actionSelection = mySelectionPage.getActionSelection(); + + final IProject[] projectsToShare; + if (actionSelection != GitSelectWizardPage.ACTION_DIALOG_SHARE) { + projectsToShare = getAddedProjects(); + } else { + projectsToShare = mySharePage.getSelectedProjects(); + } + + getContainer().run(true, true, new IRunnableWithProgress() { + + public void run(IProgressMonitor monitor) + throws InvocationTargetException, InterruptedException { + + if (actionSelection != GitSelectWizardPage.ACTION_DIALOG_SHARE) { + // in case of the share page, the import is done by the + // share page itself + // TODO this currently must be run in the UI Thread due + // to access to + // SWT widgets + importProjects(); + } + + if (actionSelection != GitSelectWizardPage.ACTION_NO_SHARE) { + + // TODO scheduling rule? + for (IProject prj : projectsToShare) { + if (monitor.isCanceled()) + throw new InterruptedException(); + // + ConnectProviderOperation connectProviderOperation = new ConnectProviderOperation( + prj, myRepository.getDirectory()); + try { + connectProviderOperation.run(monitor); + } catch (CoreException e) { + throw new InvocationTargetException(e); + } + } + + } + + } + }); + } catch (InvocationTargetException e) { + Activator + .handleError(e.getCause().getMessage(), e.getCause(), true); + return false; + } catch (InterruptedException e) { + Activator.handleError( + UIText.GitCreateProjectViaWizardWizard_AbortedMessage, e, + true); + return false; + } + return true; + + } + + /** + * + */ + public void importProjects() { + + // TODO progress monitoring and cancellation + Display.getDefault().syncExec(new Runnable() { + + public void run() { + + switch (mySelectionPage.getWizardSelection()) { + case GitSelectWizardPage.EXISTING_PROJECTS_WIZARD: + myProjectsImportPage.createProjects(); + break; + case GitSelectWizardPage.NEW_WIZARD: + new NewWizardAction(PlatformUI.getWorkbench() + .getActiveWorkbenchWindow()).run(); + break; + case GitSelectWizardPage.GENERAL_WIZARD: + try { + final String projectName = myCreateGeneralProjectPage + .getProjectName(); + getContainer().run(true, false, + new WorkspaceModifyOperation() { + + @Override + protected void execute( + IProgressMonitor monitor) + throws CoreException, + InvocationTargetException, + InterruptedException { + + final IProjectDescription desc = ResourcesPlugin + .getWorkspace() + .newProjectDescription( + projectName); + desc.setLocation(new Path(myGitDir)); + + IProject prj = ResourcesPlugin + .getWorkspace().getRoot() + .getProject(desc.getName()); + prj.create(desc, monitor); + prj.open(monitor); + + ResourcesPlugin.getWorkspace() + .getRoot().refreshLocal( + IResource.DEPTH_ONE, + monitor); + + } + }); + } catch (InvocationTargetException e1) { + Activator.handleError(e1.getMessage(), e1 + .getTargetException(), true); + } catch (InterruptedException e1) { + Activator.handleError(e1.getMessage(), e1, true); + } + break; + + } + } + }); + } + + /** + * @return the projects added to the workspace since the start of this + * wizard + */ + public IProject[] getAddedProjects() { + + IProject[] currentProjects = ResourcesPlugin.getWorkspace().getRoot() + .getProjects(); + + List newProjects = new ArrayList(); + + for (IProject current : currentProjects) { + boolean found = false; + for (IProject previous : previousProjects) { + if (previous.equals(current)) { + found = true; + break; + } + } + if (!found) { + newProjects.add(current); + } + } + + return newProjects.toArray(new IProject[0]); + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitProjectsImportPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitProjectsImportPage.java index 043e7c19..38732a43 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitProjectsImportPage.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitProjectsImportPage.java @@ -212,16 +212,27 @@ public class GitProjectsImportPage extends WizardPage { private boolean share; + private final boolean showShare; + /** * Creates a new project creation wizard page. + * @param showShareCheckbox */ - public GitProjectsImportPage() { + public GitProjectsImportPage(boolean showShareCheckbox) { super("gitWizardExternalProjectsPage"); //$NON-NLS-1$ + this.showShare = showShareCheckbox; setPageComplete(false); setTitle(UIText.WizardProjectsImportPage_ImportProjectsTitle); setDescription(UIText.WizardProjectsImportPage_ImportProjectsDescription); } + /** + * + */ + public GitProjectsImportPage(){ + this(true); + } + public void createControl(Composite parent) { initializeDialogUnits(parent); @@ -250,15 +261,19 @@ public class GitProjectsImportPage extends WizardPage { optionsGroup.setLayout(new GridLayout()); optionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - shareCheckBox = new Button(optionsGroup, SWT.CHECK); - shareCheckBox.setText(UIText.WizardProjectsImportPage_enableGit); - shareCheckBox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - shareCheckBox.setSelection(share = true); - shareCheckBox.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent e) { - share = shareCheckBox.getSelection(); - } - }); + if (showShare) { + shareCheckBox = new Button(optionsGroup, SWT.CHECK); + shareCheckBox.setText(UIText.WizardProjectsImportPage_enableGit); + shareCheckBox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + shareCheckBox.setSelection(share = true); + shareCheckBox.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + share = shareCheckBox.getSelection(); + } + }); + } else { + share = false; + } } /** diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectWizardPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectWizardPage.java new file mode 100644 index 00000000..5217deb6 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitSelectWizardPage.java @@ -0,0 +1,212 @@ +/******************************************************************************* + * Copyright (c) 2010 SAP AG. + * 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 + *******************************************************************************/ +package org.eclipse.egit.ui.internal.clone; + +import org.eclipse.egit.ui.Activator; +import org.eclipse.egit.ui.UIText; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; + +/** + * Asks the user to select a wizard and what to do with the imported projects + * (automatic/manual/no share) + */ +public class GitSelectWizardPage extends WizardPage { + + /** */ + public static final int EXISTING_PROJECTS_WIZARD = 0; + + /** */ + public static final int NEW_WIZARD = 1; + + /** */ + public static final int GENERAL_WIZARD = 2; + + // TODO check if we need/can support Import... wizard + // see also remarks in GitCreateProjectViaWizardWizard + + /** */ + public static final int ACTION_DIALOG_SHARE = 0; + + /** */ + public static final int ACTION_AUTO_SHARE = 1; + + /** */ + public static final int ACTION_NO_SHARE = 2; + + private static final String PREF_WIZ = "GitSelectWizardPageWizardSel"; //$NON-NLS-1$ + + private static final String PREF_ACT = "GitSelectWizardPageActionSel"; //$NON-NLS-1$ + + Button importExisting; + + Button newProjectWizard; + + Button generalWizard; + + Button actionAutoShare; + + Button actionDialogShare; + + Button actionNothing; + + /** + * Default constructor + */ + public GitSelectWizardPage() { + super(GitSelectWizardPage.class.getName()); + setTitle(UIText.GitSelectWizardPage_WizardTitle); + } + + public void createControl(Composite parent) { + + Composite main = new Composite(parent, SWT.NO_RADIO_GROUP); + + main.setLayout(new GridLayout(1, false)); + + SelectionListener sl = new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + checkPage(); + } + }; + + Group wizardType = new Group(main, SWT.SHADOW_ETCHED_IN); + GridDataFactory.fillDefaults().grab(true, false).applyTo(wizardType); + wizardType.setText(UIText.GitSelectWizardPage_ProjectCreationHeader); + wizardType.setLayout(new GridLayout(1, false)); + + importExisting = new Button(wizardType, SWT.RADIO); + importExisting.setText(UIText.GitSelectWizardPage_ImportExistingButton); + importExisting.addSelectionListener(sl); + + newProjectWizard = new Button(wizardType, SWT.RADIO); + newProjectWizard.setText(UIText.GitSelectWizardPage_UseNewProjectsWizardButton); + newProjectWizard.addSelectionListener(sl); + + generalWizard = new Button(wizardType, SWT.RADIO); + generalWizard.setText(UIText.GitSelectWizardPage_ImportAsGeneralButton); + generalWizard.addSelectionListener(sl); + + Group afterImportAction = new Group(main, SWT.SHADOW_ETCHED_IN); + GridDataFactory.fillDefaults().grab(true, false).applyTo( + afterImportAction); + afterImportAction + .setText(UIText.GitSelectWizardPage_SharingProjectsHeader); + afterImportAction.setLayout(new GridLayout(1, false)); + + actionAutoShare = new Button(afterImportAction, SWT.RADIO); + actionAutoShare + .setText(UIText.GitSelectWizardPage_AutoShareButton); + actionAutoShare.addSelectionListener(sl); + + actionDialogShare = new Button(afterImportAction, SWT.RADIO); + actionDialogShare.setText(UIText.GitSelectWizardPage_InteractiveShareButton); + actionDialogShare.addSelectionListener(sl); + + actionNothing = new Button(afterImportAction, SWT.RADIO); + actionNothing.setText(UIText.GitSelectWizardPage_NoShareButton); + actionNothing.addSelectionListener(sl); + + IDialogSettings settings = Activator.getDefault().getDialogSettings(); + int previousWiz; + try { + previousWiz = settings.getInt(PREF_WIZ); + } catch (NumberFormatException e) { + previousWiz = EXISTING_PROJECTS_WIZARD; + } + switch (previousWiz) { + case EXISTING_PROJECTS_WIZARD: + importExisting.setSelection(true); + break; + case GENERAL_WIZARD: + generalWizard.setSelection(true); + break; + case NEW_WIZARD: + newProjectWizard.setEnabled(true); + break; + + } + + int previousAct; + try { + previousAct = settings.getInt(PREF_ACT); + } catch (NumberFormatException e) { + previousAct = ACTION_AUTO_SHARE; + } + switch (previousAct) { + case ACTION_AUTO_SHARE: + actionAutoShare.setSelection(true); + break; + case ACTION_DIALOG_SHARE: + actionDialogShare.setSelection(true); + break; + case ACTION_NO_SHARE: + actionNothing.setSelection(true); + break; + } + + setControl(main); + + } + + /** + * @return the wizard selection + */ + public int getWizardSelection() { + if (importExisting.getSelection()) + return EXISTING_PROJECTS_WIZARD; + if (newProjectWizard.getSelection()) + return NEW_WIZARD; + if (generalWizard.getSelection()) + return GENERAL_WIZARD; + return -1; + } + + /** + * @return the action selection + */ + public int getActionSelection() { + if (actionAutoShare.getSelection()) + return ACTION_AUTO_SHARE; + if (actionDialogShare.getSelection()) + return ACTION_DIALOG_SHARE; + if (actionNothing.getSelection()) + return ACTION_NO_SHARE; + return -1; + } + + private void checkPage() { + + // we save the selected radio button in the preferences + IDialogSettings settings = Activator.getDefault().getDialogSettings(); + + settings.put(PREF_WIZ, getWizardSelection()); + settings.put(PREF_ACT, getActionSelection()); + + setErrorMessage(null); + try { + // no special checks yet + } finally { + setPageComplete(getErrorMessage() == null); + } + } +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitShareProjectsPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitShareProjectsPage.java new file mode 100644 index 00000000..3aef17ca --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitShareProjectsPage.java @@ -0,0 +1,246 @@ +/******************************************************************************* + * Copyright (c) 2010 SAP AG. + * 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 + *******************************************************************************/ +package org.eclipse.egit.ui.internal.clone; + +import java.io.File; +import java.io.FilenameFilter; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.egit.ui.Activator; +import org.eclipse.egit.ui.UIText; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.CheckStateChangedEvent; +import org.eclipse.jface.viewers.CheckboxTableViewer; +import org.eclipse.jface.viewers.ICheckStateListener; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.team.core.RepositoryProvider; + +/** + * Displays a list of projects with their containing Git repository and check + * box for sharing these projects with the Git Team Provider + *

+ * TODO add selectAll/unselectAll/toggleSelection? + */ +public class GitShareProjectsPage extends WizardPage { + + CheckboxTableViewer tv; + + private final FilenameFilter myFilenameFilter = new FilenameFilter() { + + public boolean accept(File dir, String name) { + return name.equals(Constants.DOT_GIT); + } + }; + + /** + * Default constructor + */ + public GitShareProjectsPage() { + super(GitShareProjectsPage.class.getName()); + setTitle(UIText.GitShareProjectsPage_PageTitle); + setPageComplete(false); + } + + public void createControl(Composite parent) { + + Composite main = new Composite(parent, SWT.NONE); + main.setLayout(new GridLayout(1, false)); + tv = CheckboxTableViewer.newCheckList(main, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo(tv.getTable()); + + TableColumn name = new TableColumn(tv.getTable(), SWT.NONE); + name.setWidth(200); + name.setText(UIText.GitShareProjectsPage_ProjectNameLabel); + + TableColumn repo = new TableColumn(tv.getTable(), SWT.NONE); + repo.setWidth(400); + repo.setText(UIText.GitShareProjectsPage_RepositoryLabel); + + tv.getTable().setHeaderVisible(true); + + tv.setContentProvider(new IStructuredContentProvider() { + + public void inputChanged(Viewer viewer, Object oldInput, + Object newInput) { + // nothing + } + + public void dispose() { + // nothing + } + + public Object[] getElements(Object inputElement) { + return (Object[]) inputElement; + } + }); + + tv.setLabelProvider(new ITableLabelProvider() { + + public void removeListener(ILabelProviderListener listener) { + // ignore + } + + public boolean isLabelProperty(Object element, String property) { + return false; + } + + public void dispose() { + // nothing + } + + public void addListener(ILabelProviderListener listener) { + // ignore + } + + public String getColumnText(Object element, int columnIndex) { + switch (columnIndex) { + case 0: + return ((IProject) element).getName(); + case 1: + String actRepo = getRepository((IProject) element); + if (actRepo == null) + return UIText.GitShareProjectsPage_NoRepoFoundMessage; + return actRepo; + default: + return null; + } + } + + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + }); + + tv.addCheckStateListener(new ICheckStateListener() { + + public void checkStateChanged(CheckStateChangedEvent event) { + checkPage(); + } + }); + + setControl(main); + } + + @Override + public void setVisible(boolean visible) { + if (visible) { + // when this becomes visible, we have to ask the wizard to import + // the projects + final GitCreateProjectViaWizardWizard wiz = (GitCreateProjectViaWizardWizard) getWizard(); + // TODO scheduling rule + try { + getContainer().run(false, true, new IRunnableWithProgress() { + + public void run(IProgressMonitor monitor) + throws InvocationTargetException, + InterruptedException { + wiz.importProjects(); + + } + + }); + } catch (InvocationTargetException e) { + Activator.handleError(e.getCause().getMessage(), e.getCause(), + true); + } catch (InterruptedException e) { + Activator.handleError(UIText.GitShareProjectsPage_AbortedMessage, e, true); + } + + setProjects(wiz.getAddedProjects()); + + } + super.setVisible(visible); + } + + /** + * @param projects + */ + public void setProjects(IProject[] projects) { + tv.setInput(projects); + tv.setAllChecked(true); + checkPage(); + } + + /** + * @return the selected projects + */ + public IProject[] getSelectedProjects() { + List prj = new ArrayList(); + for (Object o : tv.getCheckedElements()) { + prj.add((IProject) o); + } + return prj.toArray(new IProject[0]); + + } + + private String getRepository(IProject element) { + File locationFile = new File(element.getLocationURI()); + return checkFileRecursive(locationFile); + } + + private String checkFileRecursive(File locationFile) { + if (locationFile == null) + return null; + if (locationFile.list(myFilenameFilter).length > 0) + return locationFile.getPath(); + return checkFileRecursive(locationFile.getParentFile()); + } + + private void checkPage() { + setErrorMessage(null); + try { + // of course we need at least one project + IProject[] projects = (IProject[]) tv.getInput(); + if (projects == null || projects.length == 0) { + setErrorMessage(UIText.GitShareProjectsPage_NoNewProjectMessage); + return; + } + + Object[] selected = tv.getCheckedElements(); + if (selected.length == 0) { + setErrorMessage(UIText.GitShareProjectsPage_NothingSelectedMessage); + return; + } + // not all selected projects may be share-able here + for (Object obj : selected) { + IProject prj = (IProject) obj; + if (getRepository(prj) == null) { + setErrorMessage(NLS.bind( + UIText.GitShareProjectsPage_NoRepoForProjectMessage, prj.getName())); + return; + } + if (RepositoryProvider.getProvider(prj) != null) + setErrorMessage(NLS.bind(UIText.GitShareProjectsPage_ProjectAlreadySharedMessage, prj + .getName())); + } + + } finally { + setPageComplete(getErrorMessage() == null); + } + } + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesView.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesView.java index 6b666a64..4edffc1a 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesView.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/RepositoriesView.java @@ -51,7 +51,7 @@ import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIIcons; import org.eclipse.egit.ui.UIText; import org.eclipse.egit.ui.internal.clone.GitCloneWizard; -import org.eclipse.egit.ui.internal.clone.GitImportProjectsWizard; +import org.eclipse.egit.ui.internal.clone.GitCreateProjectViaWizardWizard; import org.eclipse.egit.ui.internal.repository.RepositoryTreeNode.RepositoryTreeNodeType; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; @@ -67,7 +67,6 @@ 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.Wizard; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; @@ -75,6 +74,9 @@ import org.eclipse.jgit.lib.RepositoryConfig; import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.MenuDetectEvent; import org.eclipse.swt.events.MenuDetectListener; import org.eclipse.swt.events.SelectionAdapter; @@ -535,6 +537,7 @@ public class RepositoriesView extends ViewPart implements ISelectionProvider, return new Status(IStatus.ERROR, Activator .getPluginId(), e1.getMessage(), e1); } + return Status.OK_STATUS; } }; @@ -714,6 +717,10 @@ public class RepositoriesView extends ViewPart implements ISelectionProvider, new MenuItem(men, SWT.SEPARATOR); + createImportProjectItem(men, repo, repo.getWorkDir().getPath()); + + new MenuItem(men, SWT.SEPARATOR); + MenuItem openPropsView = new MenuItem(men, SWT.PUSH); openPropsView.setText(UIText.RepositoriesView_OpenPropertiesMenu); openPropsView.addSelectionListener(new SelectionAdapter() { @@ -730,6 +737,10 @@ public class RepositoriesView extends ViewPart implements ISelectionProvider, } }); + + new MenuItem(men, SWT.SEPARATOR); + + createCopyPathItem(men, repo.getDirectory().getPath()); } if (node.getType() == RepositoryTreeNodeType.REMOTES) { @@ -974,18 +985,46 @@ public class RepositoriesView extends ViewPart implements ISelectionProvider, } }); - } - if (node.getType() == RepositoryTreeNodeType.FOLDER) { - String path = ((File) node.getObject()).getAbsolutePath(); - createImportProjectItem(men, node.getRepository(), path); + new MenuItem(men, SWT.SEPARATOR); + createCopyPathItem(men, file.getPath()); } if (node.getType() == RepositoryTreeNodeType.WORKINGDIR) { String path = node.getRepository().getWorkDir().getAbsolutePath(); createImportProjectItem(men, node.getRepository(), path); + new MenuItem(men, SWT.SEPARATOR); + createCopyPathItem(men, path); } + if (node.getType() == RepositoryTreeNodeType.FOLDER) { + String path = ((File) node.getObject()).getPath(); + createImportProjectItem(men, node.getRepository(), path); + new MenuItem(men, SWT.SEPARATOR); + createCopyPathItem(men, path); + } + + } + + private void createCopyPathItem(Menu men, final String path) { + + MenuItem copyPath; + copyPath = new MenuItem(men, SWT.PUSH); + copyPath.setText(UIText.RepositoriesView_CopyPathToClipboardMenu); + copyPath.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + Clipboard clipboard = new Clipboard(null); + TextTransfer textTransfer = TextTransfer.getInstance(); + Transfer[] transfers = new Transfer[] { textTransfer }; + Object[] data = new Object[] { path }; + clipboard.setContents(data, transfers); + clipboard.dispose(); + } + + }); + } private void openFile(File file) { @@ -1004,30 +1043,51 @@ public class RepositoriesView extends ViewPart implements ISelectionProvider, private void createImportProjectItem(Menu men, final Repository repo, final String path) { - MenuItem importProjects; - importProjects = new MenuItem(men, SWT.PUSH); - importProjects - .setText(UIText.RepositoriesView_ImportExistingProjects_MenuItem); - importProjects.addSelectionListener(new SelectionAdapter() { + + MenuItem startWizard; + startWizard = new MenuItem(men, SWT.PUSH); + startWizard.setText(UIText.RepositoriesView_ImportProjectsMenu); + startWizard.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - // Instead of the generic ExternalProjectImportWizard - // from the org.eclipse.ui.ide plug-in, we use our - // own wizard (the generic one does not allow to set the - // path in 3.4; in addition, we have added project filtering - // capabilities) - Wizard wiz = new GitImportProjectsWizard(repo, path); - - WizardDialog dlg = new WizardDialog(getSite().getShell(), wiz); + WizardDialog dlg = new WizardDialog(getSite().getShell(), + new GitCreateProjectViaWizardWizard(repo, path)); if (dlg.open() == Window.OK) - // TODO if we drop the "existing projects" node, we can - // probably do without refresh scheduleRefresh(); } }); + + // we could start the ImportWizard here, + // unfortunately, this fails within a wizard + // startWizard = new MenuItem(men, SWT.PUSH); + // startWizard.setText("Start the Import wizard..."); + // startWizard.addSelectionListener(new SelectionAdapter() { + // + // @Override + // public void widgetSelected(SelectionEvent e) { + // + // IHandlerService handlerService = (IHandlerService) getSite() + // .getWorkbenchWindow().getWorkbench().getService( + // IHandlerService.class); + // + // try { + // handlerService.executeCommand("org.eclipse.ui.file.import", //$NON-NLS-1$ + // null); + // } catch (ExecutionException e1) { + // Activator.handleError(e1.getMessage(), e1, true); + // } catch (NotDefinedException e1) { + // Activator.handleError(e1.getMessage(), e1, true); + // } catch (NotEnabledException e1) { + // Activator.handleError(e1.getMessage(), e1, true); + // } catch (NotHandledException e1) { + // Activator.handleError(e1.getMessage(), e1, true); + // } + // } + // + // }); } private void addActionsToToolbar() { diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties index 40938bd3..c72ecabe 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties @@ -551,6 +551,7 @@ RepositoriesView_ConfirmDeleteRemoteHeader=Confirm deletion of remote configurat RepositoriesView_ConfirmDeleteRemoteMessage=This will remove remote configuration {0} completely, are you sure? RepositoriesView_ConfirmProjectDeletion_Question={0} projects must be deleted, continue? RepositoriesView_ConfirmProjectDeletion_WindowTitle=Confirm project deletion +RepositoriesView_CopyPathToClipboardMenu=Copy path to clipboard RepositoriesView_CreateFetch_menu=Create Fetch... RepositoriesView_CreatePush_menu=Create Push... RepositoriesView_Error_WindowTitle=Error @@ -559,6 +560,7 @@ RepositoriesView_ExistingProjects_Nodetext=Existing Projects RepositoriesView_Import_Button=Import... RepositoriesView_ImportExistingProjects_MenuItem=Import Existing projects... RepositoriesView_ImportProject_MenuItem=Import +RepositoriesView_ImportProjectsMenu=Import projects... RepositoriesView_ImportRepository_MenuItem=Import Git Repository... RepositoriesView_LinkWithSelection_action=Link with selection RepositoriesView_NewRemoteMenu=New remote... @@ -586,6 +588,33 @@ DiscardChangesAction_refreshErrorTitle=Error During Refresh DiscardChangesAction_refreshErrorMessage=Some of the selected resources could not be refreshed. GitCompareFileRevisionEditorInput_contentIdentifier=Problem getting content identifier +GitCreateGeneralProjectPage_DirLabel=Directory +GitCreateGeneralProjectPage_DirNotExistMessage=Directory {0} does not exist +GitCreateGeneralProjectPage_EnterProjectNameMessage=Please provide a project name +GitCreateGeneralProjectPage_FileExistsInDirMessage=A {0} file already exists in directoy {1} +GitCreateGeneralProjectPage_FileNotDirMessage=File {0} is not a directory +GitCreateGeneralProjectPage_PorjectAlreadyExistsMessage=Project {0} already exists +GitCreateGeneralProjectPage_ProjectNameLabel=Project name +GitCreateProjectViaWizardWizard_AbortedMessage=Action was aborted +GitCreateProjectViaWizardWizard_WizardTitle=Import projects from Git Repository {0} +GitSelectWizardPage_AutoShareButton=Try to share newly created projects automatically +GitSelectWizardPage_ImportAsGeneralButton=Import as General Project +GitSelectWizardPage_ImportExistingButton=Import Existing Projects +GitSelectWizardPage_InteractiveShareButton=Share new projects interactively +GitSelectWizardPage_NoShareButton=Do not share new projects +GitSelectWizardPage_ProjectCreationHeader=Method for project creation +GitSelectWizardPage_SharingProjectsHeader=Method for sharing projects after project creation +GitSelectWizardPage_UseNewProjectsWizardButton=Use the New Projects wizard +GitSelectWizardPage_WizardTitle=Choose how to import and share projects from at Git Repository +GitShareProjectsPage_AbortedMessage=Action was aborted +GitShareProjectsPage_NoNewProjectMessage=No new projects found +GitShareProjectsPage_NoRepoForProjectMessage=No Git repository for project {0} +GitShareProjectsPage_NoRepoFoundMessage=No repository found +GitShareProjectsPage_NothingSelectedMessage=Nothing selected +GitShareProjectsPage_PageTitle=Share projects with Git +GitShareProjectsPage_ProjectAlreadySharedMessage=Project {0} already shared +GitShareProjectsPage_ProjectNameLabel=Project name +GitShareProjectsPage_RepositoryLabel=Git Repository UIIcons_errorDeterminingIconBase=Can't determine icon base. UIIcons_errorLoadingPluginImage=Can't load plugin image. \ No newline at end of file -- 2.11.4.GIT