diff options
author | Tomasz Zarna | 2012-02-17 15:06:57 +0000 |
---|---|---|
committer | Matthias Sohn | 2012-02-17 15:06:57 +0000 |
commit | 7205115b9a2280ab366c75a03d0348245a4243a7 (patch) | |
tree | decdf4943c03ae34bfda9d8cfa70446224e11780 | |
parent | c5cd6e4b637cf9b904458177db2a08e0ddbe66ce (diff) | |
download | egit-7205115b9a2280ab366c75a03d0348245a4243a7.tar.gz egit-7205115b9a2280ab366c75a03d0348245a4243a7.tar.xz egit-7205115b9a2280ab366c75a03d0348245a4243a7.zip |
Allow to save patches in the workspace
CQ: 6030
Bug: 368774
Change-Id: Ib3f78eceaea6f9ca3f916622d836b1d39613fd08
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
Signed-off-by: Chris Aniszczyk <zx@twitter.com>
4 files changed, 733 insertions, 208 deletions
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 140c7fc397..f76248f20a 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 @@ -3037,6 +3037,51 @@ public class UIText extends NLS { public static String GitCreatePatchWizard_LinesOfContext; /** */ + public static String GitCreatePatchWizard_ReadOnlyTitle; + + /** */ + public static String GitCreatePatchWizard_ReadOnlyMsg; + + /** */ + public static String GitCreatePatchWizard_OverwriteTitle; + + /** */ + public static String GitCreatePatchWizard_OverwriteMsg; + + /** */ + public static String GitCreatePatchWizard_Workspace; + + /** */ + public static String GitCreatePatchWizard_WorkspacePatchDialogTitle; + + /** */ + public static String GitCreatePatchWizard_WorkspacePatchDialogDescription; + + /** */ + public static String GitCreatePatchWizard_WorkspacePatchDialogEnterFileName; + + /** */ + public static String GitCreatePatchWizard_WorkspacePatchDialogEnterValidLocation; + + /** */ + public static String GitCreatePatchWizard_WorkspacePatchDialogFileName; + + /** */ + public static String GitCreatePatchWizard_WorkspacePatchDialogSavePatch; + + /** */ + public static String GitCreatePatchWizard_WorkspacePatchEnterValidFileName; + + /** */ + public static String GitCreatePatchWizard_WorkspacePatchFolderExists; + + /** */ + public static String GitCreatePatchWizard_WorkspacePatchProjectClosed; + + /** */ + public static String GitCreatePatchWizard_WorkspacePatchSelectByBrowsing; + + /** */ public static String GitCreateProjectViaWizardWizard_AbortedMessage; /** */ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitCreatePatchWizard.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitCreatePatchWizard.java index bbf7f48a54..10edd0b3af 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitCreatePatchWizard.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitCreatePatchWizard.java @@ -9,6 +9,7 @@ * Contributors: * Stefan Lay (SAP AG) - initial implementation * Daniel Megert <daniel_megert@ch.ibm.com> - Create Patch... dialog should not set file location - http://bugs.eclipse.org/361405 + * Tomasz Zarna <Tomasz.Zarna@pl.ibm.com> - Allow to save patches in Workspace *******************************************************************************/ package org.eclipse.egit.ui.internal.history; @@ -20,9 +21,7 @@ import java.io.Writer; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.Path; import org.eclipse.egit.core.op.CreatePatchOperation; import org.eclipse.egit.core.op.CreatePatchOperation.DiffHeaderFormat; import org.eclipse.egit.ui.Activator; @@ -31,6 +30,7 @@ import org.eclipse.egit.ui.UIText; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.resource.ImageDescriptor; @@ -52,15 +52,10 @@ import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; 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.FileDialog; import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; @@ -148,8 +143,11 @@ public class GitCreatePatchWizard extends Wizard { operation.setHeaderFormat(optionsPage.getSelectedHeaderFormat()); operation.setContextLines(Integer.parseInt(optionsPage.contextLines.getText())); - final boolean isFile = locationPage.fsRadio.getSelection(); - final String fileName = locationPage.fsPathText.getText(); + final File file = !locationPage.fsRadio.getSelection() ? locationPage + .getFile() : null; + + if (!(file == null || validateFile(file))) + return false; try { getContainer().run(true, true, new IRunnableWithProgress() { @@ -159,11 +157,10 @@ public class GitCreatePatchWizard extends Wizard { operation.execute(monitor); String content = operation.getPatchContent(); - if (isFile) { - writeToFile(fileName, content); - } else { + if (file != null) + writeToFile(file, content); + else copyToClipboard(content); - } } catch (IOException e) { throw new InvocationTargetException(e); } catch (CoreException e) { @@ -196,9 +193,9 @@ public class GitCreatePatchWizard extends Wizard { }); } - private void writeToFile(final String fileName, String content) + private void writeToFile(final File file, String content) throws IOException { - Writer output = new BufferedWriter(new FileWriter(fileName)); + Writer output = new BufferedWriter(new FileWriter(file)); try { // FileWriter always assumes default encoding is // OK! @@ -208,202 +205,31 @@ public class GitCreatePatchWizard extends Wizard { } } - /** - * A wizard page to choose the target location - */ - public class LocationPage extends WizardPage { - - private static final String PATH_KEY = "GitCreatePatchWizard.LocationPage.path"; //$NON-NLS-1$ - - private Button cpRadio; - - private Button fsRadio; - - private Text fsPathText; - - private Button fsBrowseButton; - - private boolean pageValid; - - /** - * @param pageName - * @param title - * @param titleImage - */ - protected LocationPage(String pageName, String title, - ImageDescriptor titleImage) { - super(pageName, title, titleImage); - } - - public void createControl(Composite parent) { - final Composite composite = new Composite(parent, SWT.NULL); - GridLayout gridLayout = new GridLayout(); - gridLayout.numColumns = 3; - composite.setLayout(gridLayout); - composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - initializeDialogUnits(composite); - - // clipboard - GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); - gd.horizontalSpan = 3; - cpRadio = new Button(composite, SWT.RADIO); - cpRadio.setText(UIText.GitCreatePatchWizard_Clipboard); - cpRadio.setLayoutData(gd); - cpRadio.setSelection(true); - - // filesystem - fsRadio = new Button(composite, SWT.RADIO); - fsRadio.setText(UIText.GitCreatePatchWizard_File); - fsRadio.setSelection(false); - - fsPathText = new Text(composite, SWT.BORDER); - gd = new GridData(GridData.FILL_HORIZONTAL); - fsPathText.setLayoutData(gd); - fsPathText.setText(createFileName()); - fsPathText.setEnabled(false); - - fsBrowseButton = new Button(composite, SWT.PUSH); - fsBrowseButton.setText(UIText.GitCreatePatchWizard_Browse); - GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); - int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); - Point minSize = fsBrowseButton.computeSize(SWT.DEFAULT, - SWT.DEFAULT, true); - data.widthHint = Math.max(widthHint, minSize.x); - fsBrowseButton.setLayoutData(data); - fsBrowseButton.setEnabled(false); - - cpRadio.addListener(SWT.Selection, new Listener() { - public void handleEvent(Event event) { - // disable other input controls - if (((Button) event.widget).getSelection()) { - fsPathText.setEnabled(false); - fsBrowseButton.setEnabled(false); - validatePage(); - } - } - }); - - fsRadio.addListener(SWT.Selection, new Listener() { - - public void handleEvent(Event event) { - if (((Button) event.widget).getSelection()) { - // enable filesystem input controls - fsPathText.setEnabled(true); - fsBrowseButton.setEnabled(true); - // set focus to filesystem input text control - fsPathText.setFocus(); - validatePage(); - } - } - }); - - fsPathText.addModifyListener(new ModifyListener() { - - public void modifyText(ModifyEvent e) { - if (validatePage()) { - IPath filePath= Path.fromOSString(fsPathText.getText()).removeLastSegments(1); - getDialogSettings().put(PATH_KEY, filePath.toPortableString()); - } - } - }); - - fsBrowseButton.addListener(SWT.Selection, new Listener() { - public void handleEvent(Event event) { - final FileDialog dialog = new FileDialog(getShell(), - SWT.PRIMARY_MODAL | SWT.SAVE); - if (pageValid) { - final File file = new File(fsPathText.getText()); - dialog.setFilterPath(file.getParent()); - dialog.setFileName(file.getName()); - } else { - dialog.setFileName(""); //$NON-NLS-1$ - } - dialog.setText(""); //$NON-NLS-1$ - final String path = dialog.open(); - if (path != null) - fsPathText.setText(new Path(path).toOSString()); - validatePage(); - } - }); - - Dialog.applyDialogFont(composite); - setControl(composite); - - } - - private String createFileName() { - String suggestedFileName = commit != null ? CreatePatchOperation - .suggestFileName(commit) : db.getWorkTree().getName() - .concat(".patch"); //$NON-NLS-1$ - String path = getDialogSettings().get(PATH_KEY); - if (path != null) - return Path.fromPortableString(path).append(suggestedFileName).toOSString(); - - return (new File(System.getProperty("user.dir", ""), suggestedFileName)).getPath(); //$NON-NLS-1$ //$NON-NLS-2$ - } + private boolean validateFile(File file) { + if (file == null) + return false; - /** - * Allow the user to finish if a valid file has been entered. - * - * @return page is valid - */ - protected boolean validatePage() { - if (fsRadio.getSelection()) { - pageValid = validateFilesystemLocation(); - } else if (cpRadio.getSelection()) { - pageValid = true; - } + // Consider file valid if it doesn't exist for now. + if (!file.exists()) + return true; - /** - * Avoid draw flicker by clearing error message if all is valid. - */ - if (pageValid) { - setMessage(null); - setErrorMessage(null); - } - setPageComplete(pageValid); - return pageValid; + // The file exists. + if (!file.canWrite()) { + final String title= UIText.GitCreatePatchWizard_ReadOnlyTitle; + final String msg= UIText.GitCreatePatchWizard_ReadOnlyMsg; + final MessageDialog dialog= new MessageDialog(getShell(), title, null, msg, MessageDialog.ERROR, new String[] { IDialogConstants.OK_LABEL }, 0); + dialog.open(); + return false; } - /** - * The following conditions must hold for the file system location to be - * valid: - the path must be valid and non-empty - the path must be - * absolute - the specified file must be of type file - the parent must - * exist (new folders can be created via the browse button) - * - * @return if the location is valid - */ - private boolean validateFilesystemLocation() { - final String pathString = fsPathText.getText().trim(); - if (pathString.length() == 0 - || !new Path("").isValidPath(pathString)) { //$NON-NLS-1$ - setErrorMessage(UIText.GitCreatePatchWizard_FilesystemError); - return false; - } - - final File file = new File(pathString); - if (!file.isAbsolute()) { - setErrorMessage(UIText.GitCreatePatchWizard_FilesystemInvalidError); - return false; - } - - if (file.isDirectory()) { - setErrorMessage(UIText.GitCreatePatchWizard_FilesystemDirectoryError); - return false; - } - - if (pathString.endsWith("/") || pathString.endsWith("\\")) { //$NON-NLS-1$//$NON-NLS-2$ - setErrorMessage(UIText.GitCreatePatchWizard_FilesystemDirectoryNotExistsError); - return false; - } + final String title = UIText.GitCreatePatchWizard_OverwriteTitle; + final String msg = UIText.GitCreatePatchWizard_OverwriteMsg; + final MessageDialog dialog = new MessageDialog(getShell(), title, null, msg, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.CANCEL_LABEL }, 0); + dialog.open(); + if (dialog.getReturnCode() != 0) + return false; - final File parent = file.getParentFile(); - if (!(parent.exists() && parent.isDirectory())) { - setErrorMessage(UIText.GitCreatePatchWizard_FilesystemDirectoryNotExistsError); - return false; - } - return true; - } + return true; } /** @@ -496,12 +322,11 @@ public class GitCreatePatchWizard extends Wizard { text = text.trim(); char[] charArray = text.toCharArray(); - for (char c : charArray) { + for (char c : charArray) if(!Character.isDigit(c)) { setErrorMessage(UIText.GitCreatePatchWizard_ContextMustBePositiveInt); return false; } - } return true; } @@ -511,4 +336,12 @@ public class GitCreatePatchWizard extends Wizard { return (DiffHeaderFormat) selection.getFirstElement(); } } + + Repository getRepository() { + return db; + } + + RevCommit getCommit() { + return commit; + } }
\ No newline at end of file diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/LocationPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/LocationPage.java new file mode 100644 index 0000000000..e8966cfe57 --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/LocationPage.java @@ -0,0 +1,632 @@ +/******************************************************************************* + * Copyright (c) 2010-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: + * Tomasz Zarna <Tomasz.Zarna@pl.ibm.com> - Allow to save patches in Workspace + *******************************************************************************/ +package org.eclipse.egit.ui.internal.history; + +import java.io.File; +import java.util.ArrayList; + +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.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; +import org.eclipse.egit.core.op.CreatePatchOperation; +import org.eclipse.egit.ui.UIIcons; +import org.eclipse.egit.ui.UIText; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.model.BaseWorkbenchContentProvider; +import org.eclipse.ui.model.WorkbenchLabelProvider; +import org.eclipse.ui.views.navigator.ResourceComparator; + +/** + * A wizard page to choose the target location. + * <p> + * Extracted from {@link GitCreatePatchWizard} + */ +public class LocationPage extends WizardPage { + + private static final String PATH_KEY = "GitCreatePatchWizard.LocationPage.path"; //$NON-NLS-1$ + + private Button cpRadio; + + Button fsRadio; + + private Text fsPathText; + + private Button fsBrowseButton; + + private Button wsRadio; + + private Text wsPathText; + + private Button wsBrowseButton; + + private boolean wsBrowsed = false; + + private boolean pageValid; + + private IContainer wsSelectedContainer; + + private class LocationPageContentProvider extends BaseWorkbenchContentProvider { + //Never show closed projects + boolean showClosedProjects = false; + + public Object[] getChildren(Object element) { + if (element instanceof IWorkspace) { + // check if closed projects should be shown + IProject[] allProjects = ((IWorkspace) element).getRoot().getProjects(); + if (showClosedProjects) + return allProjects; + + ArrayList<IProject> accessibleProjects = new ArrayList<IProject>(); + for (IProject project : allProjects) { + if (project.isOpen()) + accessibleProjects.add(project); + } + return accessibleProjects.toArray(); + } + return super.getChildren(element); + } + } + + private class WorkspaceDialog extends TitleAreaDialog { + + protected TreeViewer wsTreeViewer; + protected Text wsFilenameText; + protected Image dlgTitleImage; + + private boolean modified = false; + + public WorkspaceDialog(Shell shell) { + super(shell); + } + + protected Control createContents(Composite parent) { + Control control = super.createContents(parent); + setTitle(UIText.GitCreatePatchWizard_WorkspacePatchDialogTitle); + setMessage(UIText.GitCreatePatchWizard_WorkspacePatchDialogDescription); + //create title image + dlgTitleImage = UIIcons.WIZBAN_CREATE_PATCH.createImage(); + setTitleImage(dlgTitleImage); + + return control; + } + + protected Control createDialogArea(Composite parent){ + Composite parentComposite = (Composite) super.createDialogArea(parent); + + // create a composite with standard margins and spacing + Composite composite = new Composite(parentComposite, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); + layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); + layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_BOTH)); + composite.setFont(parentComposite.getFont()); + + getShell().setText(UIText.GitCreatePatchWizard_WorkspacePatchDialogSavePatch); + + wsTreeViewer = new TreeViewer(composite, SWT.BORDER); + final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true); + gd.widthHint= 550; + gd.heightHint= 250; + wsTreeViewer.getTree().setLayoutData(gd); + + wsTreeViewer.setContentProvider(new LocationPageContentProvider()); + wsTreeViewer.setComparator(new ResourceComparator(ResourceComparator.NAME)); + wsTreeViewer.setLabelProvider(new WorkbenchLabelProvider()); + wsTreeViewer.setInput(ResourcesPlugin.getWorkspace()); + + //Open to whatever is selected in the workspace field + IPath existingWorkspacePath = new Path(wsPathText.getText()); + //Ensure that this workspace path is valid + IResource selectedResource = ResourcesPlugin.getWorkspace().getRoot().findMember(existingWorkspacePath); + if (selectedResource != null) { + wsTreeViewer.expandToLevel(selectedResource, 0); + wsTreeViewer.setSelection(new StructuredSelection(selectedResource)); + } + + final Composite group = new Composite(composite, SWT.NONE); + layout = new GridLayout(2, false); + layout.marginWidth = 0; + group.setLayout(layout); + group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + + final Label label = new Label(group, SWT.NONE); + label.setLayoutData(new GridData()); + label.setText(UIText.GitCreatePatchWizard_WorkspacePatchDialogFileName); + + wsFilenameText = new Text(group,SWT.BORDER); + wsFilenameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + + setupListeners(); + + return parent; + } + + protected Button createButton(Composite parent, int id, + String label, boolean defaultButton) { + Button button = super.createButton(parent, id, label, + defaultButton); + if (id == IDialogConstants.OK_ID) { + button.setEnabled(false); + } + return button; + } + + private void validateDialog() { + String fileName = wsFilenameText.getText(); + + if (fileName.equals("")) { //$NON-NLS-1$ + if (modified) { + setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchDialogEnterFileName); + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + } else { + setErrorMessage(null); + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + } + } + + // make sure that the filename is valid + if (!(ResourcesPlugin.getWorkspace().validateName(fileName, + IResource.FILE)).isOK() && modified) { + setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchEnterValidFileName); + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + } + + // Make sure that a container has been selected + if (getSelectedContainer() == null) { + setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchDialogEnterValidLocation); + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + } else { + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IPath fullPath = wsSelectedContainer.getFullPath().append( + fileName); + if (workspace.getRoot().getFolder(fullPath).exists()) { + setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchFolderExists); + getButton(IDialogConstants.OK_ID).setEnabled(false); + return; + } + } + + setErrorMessage(null); + getButton(IDialogConstants.OK_ID).setEnabled(true); + } + + protected void okPressed() { + IFile file = wsSelectedContainer.getFile(new Path( + wsFilenameText.getText())); + if (file != null) + wsPathText.setText(file.getFullPath().toString()); + + validatePage(); + super.okPressed(); + } + + private IContainer getSelectedContainer() { + Object obj = ((IStructuredSelection)wsTreeViewer.getSelection()).getFirstElement(); + if (obj instanceof IContainer) + wsSelectedContainer = (IContainer) obj; + else if (obj instanceof IFile) + wsSelectedContainer = ((IFile) obj).getParent(); + return wsSelectedContainer; + } + + protected void cancelPressed() { + validatePage(); + super.cancelPressed(); + } + + public boolean close() { + if (dlgTitleImage != null) + dlgTitleImage.dispose(); + return super.close(); + } + + void setupListeners(){ + wsTreeViewer.addSelectionChangedListener( + new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + IStructuredSelection s = (IStructuredSelection)event.getSelection(); + Object obj=s.getFirstElement(); + if (obj instanceof IContainer) + wsSelectedContainer = (IContainer) obj; + else if (obj instanceof IFile){ + IFile tempFile = (IFile) obj; + wsSelectedContainer = tempFile.getParent(); + wsFilenameText.setText(tempFile.getName()); + } + validateDialog(); + } + }); + + wsTreeViewer.addDoubleClickListener( + new IDoubleClickListener() { + public void doubleClick(DoubleClickEvent event) { + ISelection s= event.getSelection(); + if (s instanceof IStructuredSelection) { + Object item = ((IStructuredSelection)s).getFirstElement(); + if (wsTreeViewer.getExpandedState(item)) + wsTreeViewer.collapseToLevel(item, 1); + else + wsTreeViewer.expandToLevel(item, 1); + } + validateDialog(); + } + }); + + wsFilenameText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + modified = true; + validateDialog(); + } + }); + } + } + + /** + * @param pageName + * @param title + * @param titleImage + */ + protected LocationPage(String pageName, String title, + ImageDescriptor titleImage) { + super(pageName, title, titleImage); + } + + public void createControl(Composite parent) { + final Composite composite = new Composite(parent, SWT.NULL); + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 3; + composite.setLayout(gridLayout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + initializeDialogUnits(composite); + + // clipboard + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); + gd.horizontalSpan = 3; + cpRadio = new Button(composite, SWT.RADIO); + cpRadio.setText(UIText.GitCreatePatchWizard_Clipboard); + cpRadio.setLayoutData(gd); + cpRadio.setSelection(true); + + // filesystem + fsRadio = new Button(composite, SWT.RADIO); + fsRadio.setText(UIText.GitCreatePatchWizard_File); + fsRadio.setSelection(false); + + fsPathText = new Text(composite, SWT.BORDER); + gd = new GridData(GridData.FILL_HORIZONTAL); + fsPathText.setLayoutData(gd); + fsPathText.setText(createFileName()); + fsPathText.setEnabled(false); + + fsBrowseButton = new Button(composite, SWT.PUSH); + fsBrowseButton.setText(UIText.GitCreatePatchWizard_Browse); + GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); + Point minSize = fsBrowseButton.computeSize(SWT.DEFAULT, + SWT.DEFAULT, true); + data.widthHint = Math.max(widthHint, minSize.x); + fsBrowseButton.setLayoutData(data); + fsBrowseButton.setEnabled(false); + + // workspace + wsRadio = new Button(composite, SWT.RADIO); + wsRadio.setText(UIText.GitCreatePatchWizard_Workspace); + wsRadio.setSelection(false); + + wsPathText = new Text(composite, SWT.BORDER); + wsPathText.setLayoutData(gd); + wsPathText.setEnabled(false); + + wsBrowseButton = new Button(composite, SWT.PUSH); + wsBrowseButton.setText(UIText.GitCreatePatchWizard_Browse); + wsBrowseButton.setLayoutData(data); + wsBrowseButton.setEnabled(false); + + cpRadio.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + // disable other input controls + if (((Button) event.widget).getSelection()) { + fsPathText.setEnabled(false); + fsBrowseButton.setEnabled(false); + wsPathText.setEnabled(false); + wsBrowseButton.setEnabled(false); + validatePage(); + } + } + }); + + fsRadio.addListener(SWT.Selection, new Listener() { + + public void handleEvent(Event event) { + if (((Button) event.widget).getSelection()) { + // enable filesystem input controls + fsPathText.setEnabled(true); + fsBrowseButton.setEnabled(true); + wsPathText.setEnabled(false); + wsBrowseButton.setEnabled(false); + // set focus to filesystem input text control + fsPathText.setFocus(); + validatePage(); + } + } + }); + + fsPathText.addModifyListener(new ModifyListener() { + + public void modifyText(ModifyEvent e) { + if (validatePage()) { + IPath filePath= Path.fromOSString(fsPathText.getText()).removeLastSegments(1); + getDialogSettings().put(PATH_KEY, filePath.toPortableString()); + } + } + }); + + fsBrowseButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + final FileDialog dialog = new FileDialog(getShell(), + SWT.PRIMARY_MODAL | SWT.SAVE); + if (pageValid) { + final File file = new File(fsPathText.getText()); + dialog.setFilterPath(file.getParent()); + dialog.setFileName(file.getName()); + } else { + dialog.setFileName(""); //$NON-NLS-1$ + } + dialog.setText(""); //$NON-NLS-1$ + final String path = dialog.open(); + if (path != null) + fsPathText.setText(new Path(path).toOSString()); + validatePage(); + } + }); + + wsRadio.addListener(SWT.Selection, new Listener() { + + public void handleEvent(Event event) { + if (((Button) event.widget).getSelection()) { + fsPathText.setEnabled(false); + fsBrowseButton.setEnabled(false); + // enable workspace input controls + wsPathText.setEnabled(true); + wsBrowseButton.setEnabled(true); + // set focus to workspace input text control + wsPathText.setFocus(); + validatePage(); + } + } + }); + + wsPathText.addModifyListener(new ModifyListener() { + + public void modifyText(ModifyEvent e) { + if (validatePage()) { + IPath filePath= Path.fromOSString(wsPathText.getText()).removeLastSegments(1); + getDialogSettings().put(PATH_KEY, filePath.toPortableString()); + } + } + }); + + wsBrowseButton.addListener(SWT.Selection, new Listener() { + public void handleEvent(Event event) { + final WorkspaceDialog dialog = new WorkspaceDialog(getShell()); + wsBrowsed = true; + dialog.open(); + validatePage(); + } + }); + + Dialog.applyDialogFont(composite); + setControl(composite); + + } + + private String createFileName() { + String suggestedFileName = getCommit() != null ? CreatePatchOperation + .suggestFileName(getCommit()) : getRepository().getWorkTree() + .getName().concat(".patch"); //$NON-NLS-1$ + String path = getDialogSettings().get(PATH_KEY); + if (path != null) + return Path.fromPortableString(path).append(suggestedFileName).toOSString(); + + return (new File(System.getProperty("user.dir", ""), suggestedFileName)).getPath(); //$NON-NLS-1$ //$NON-NLS-2$ + } + + private RevCommit getCommit() { + return ((GitCreatePatchWizard)getWizard()).getCommit(); + } + + private Repository getRepository() { + return ((GitCreatePatchWizard)getWizard()).getRepository(); + } + + /** + * Allow the user to finish if a valid file has been entered. + * + * @return page is valid + */ + protected boolean validatePage() { + if (wsRadio.getSelection()) { + pageValid = validateWorkspaceLocation(); + }else if (fsRadio.getSelection()) { + pageValid = validateFilesystemLocation(); + } else if (cpRadio.getSelection()) { + pageValid = true; + } + + /** + * Avoid draw flicker by clearing error message if all is valid. + */ + if (pageValid) { + setMessage(null); + setErrorMessage(null); + } + setPageComplete(pageValid); + return pageValid; + } + + /** + * The following conditions must hold for the file system location to be + * valid: + * - the path must be valid and non-empty + * - the path must be absolute + * - the specified file must be of type file + * - the parent must exist (new folders can be created via the browse button) + * + * @return if the location is valid + */ + private boolean validateFilesystemLocation() { + final String pathString = fsPathText.getText().trim(); + if (pathString.length() == 0 + || !new Path("").isValidPath(pathString)) { //$NON-NLS-1$ + setErrorMessage(UIText.GitCreatePatchWizard_FilesystemError); + return false; + } + + final File file = new File(pathString); + if (!file.isAbsolute()) { + setErrorMessage(UIText.GitCreatePatchWizard_FilesystemInvalidError); + return false; + } + + if (file.isDirectory()) { + setErrorMessage(UIText.GitCreatePatchWizard_FilesystemDirectoryError); + return false; + } + + if (pathString.endsWith("/") || pathString.endsWith("\\")) { //$NON-NLS-1$//$NON-NLS-2$ + setErrorMessage(UIText.GitCreatePatchWizard_FilesystemDirectoryNotExistsError); + return false; + } + + final File parent = file.getParentFile(); + if (!(parent.exists() && parent.isDirectory())) { + setErrorMessage(UIText.GitCreatePatchWizard_FilesystemDirectoryNotExistsError); + return false; + } + return true; + } + + /** + * The following conditions must hold for the workspace location to be valid: + * - a parent must be selected in the workspace tree view + * - the resource name must be valid + * + * @return if the location is valid + */ + private boolean validateWorkspaceLocation() { + //make sure that the field actually has a filename in it - making + //sure that the user has had a chance to browse the workspace first + if (wsPathText.getText().equals("")){ //$NON-NLS-1$ + if (wsRadio.getSelection() && wsBrowsed) + setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchEnterValidFileName); + else + setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchSelectByBrowsing); + return false; + } + + //Make sure that all the segments but the last one (i.e. project + all + //folders) exist - file doesn't have to exist. It may have happened that + //some folder refactoring has been done since this path was last saved. + // + // The path will always be in format project/{folders}*/file - this + // is controlled by the workspace location dialog and by + // validatePath method when path has been entered manually. + + IPath pathToWorkspaceFile = new Path(wsPathText.getText()); + IStatus status = ResourcesPlugin.getWorkspace().validatePath(wsPathText.getText(), IResource.FILE); + if (status.isOK()) { + //Trim file name from path + IPath containerPath = pathToWorkspaceFile.removeLastSegments(1); + IResource container = ResourcesPlugin.getWorkspace().getRoot().findMember(containerPath); + if (container == null) { + if (wsRadio.getSelection()) + setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchSelectByBrowsing); + return false; + } else if (!container.isAccessible()) { + if (wsRadio.getSelection()) + setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchProjectClosed); + return false; + } else { + if (ResourcesPlugin.getWorkspace().getRoot().getFolder( + pathToWorkspaceFile).exists()) { + setErrorMessage(UIText.GitCreatePatchWizard_WorkspacePatchFolderExists); + return false; + } + } + } else { + setErrorMessage(status.getMessage()); + return false; + } + return true; + } + + /** + * @return answers a full path to a file system file or + * <code>null</code> if the user selected to save the patch in + * the clipboard. + */ + public File getFile() { + if (pageValid && fsRadio.getSelection()) + return new File(fsPathText.getText().trim()); + if (pageValid && wsRadio.getSelection()) { + final String filename= wsPathText.getText().trim(); + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + final IFile file = root.getFile(new Path(filename)); + return file.getLocation().toFile(); + } + return null; + } +}
\ No newline at end of file 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 4dd9fae613..b789dac7cb 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 @@ -1045,6 +1045,21 @@ GitCreatePatchWizard_FilesystemInvalidError=Please enter a valid location. GitCreatePatchWizard_FilesystemDirectoryError=Please enter a file name. GitCreatePatchWizard_FilesystemDirectoryNotExistsError=The specified directory does not exist. GitCreatePatchWizard_LinesOfContext=Lines of &context: +GitCreatePatchWizard_ReadOnlyTitle=Read-only file +GitCreatePatchWizard_ReadOnlyMsg=The specified file is read-only and cannot be overwritten. +GitCreatePatchWizard_OverwriteTitle=Confirm Overwrite +GitCreatePatchWizard_OverwriteMsg=A file with that name already exists. Overwrite? +GitCreatePatchWizard_Workspace=&Workspace +GitCreatePatchWizard_WorkspacePatchDialogTitle=Set a Patch Location +GitCreatePatchWizard_WorkspacePatchDialogDescription=Select a folder in the workspace and enter a name for the patch. +GitCreatePatchWizard_WorkspacePatchDialogEnterFileName=Please enter a file name. +GitCreatePatchWizard_WorkspacePatchDialogEnterValidLocation=Please enter a valid location. +GitCreatePatchWizard_WorkspacePatchDialogFileName=Fi&le name: +GitCreatePatchWizard_WorkspacePatchDialogSavePatch=Save Patch +GitCreatePatchWizard_WorkspacePatchEnterValidFileName=Please enter a valid filename. +GitCreatePatchWizard_WorkspacePatchFolderExists=The specified path points to an existing folder. +GitCreatePatchWizard_WorkspacePatchProjectClosed=The specified path points to a closed project. +GitCreatePatchWizard_WorkspacePatchSelectByBrowsing=Please select a location in the workspace by browsing. GitCreateProjectViaWizardWizard_AbortedMessage=Action was aborted GitCreateProjectViaWizardWizard_WizardTitle=Import Projects from Git Repository {0} GitImportWithDirectoriesPage_PageMessage=Depending on the wizard, you may select a directory to determine the wizard's scope |