blob: 1d1cf744204d3e5a3b1e2e582bb744970dd85249 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Sebastian Davids <sdavids@gmx.de> - layout tweaks
* Matt McCutchen <hashproduct+eclipse@gmail.com> - Bug 180358 [Apply Patch] Cursor jumps to beginning of filename field on keystroke
*******************************************************************************/
package org.eclipse.compare.internal.patch;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import org.eclipse.compare.internal.ICompareContextIds;
import org.eclipse.compare.internal.Utilities;
import org.eclipse.compare.patch.IFilePatch2;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
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.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
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.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.views.navigator.ResourceComparator;
import com.ibm.icu.text.MessageFormat;
public class InputPatchPage extends WizardPage {
// constants
protected static final int SIZING_TEXT_FIELD_WIDTH= 250;
protected static final int COMBO_HISTORY_LENGTH= 5;
// dialog store id constants
private final static String PAGE_NAME= "PatchWizardPage1"; //$NON-NLS-1$
private final static String STORE_PATCH_FILES_ID= PAGE_NAME+".PATCH_FILES"; //$NON-NLS-1$
private final static String STORE_PATCH_URLS_ID= PAGE_NAME+".PATCH_URLS"; //$NON-NLS-1$
private final static String STORE_INPUT_METHOD_ID= PAGE_NAME+".INPUT_METHOD"; //$NON-NLS-1$
private final static String STORE_WORKSPACE_PATH_ID= PAGE_NAME+".WORKSPACE_PATH"; //$NON-NLS-1$
//patch input constants
protected final static int CLIPBOARD= 1;
protected final static int FILE= 2;
protected final static int WORKSPACE= 3;
protected final static int URL= 4;
protected final static String INPUTPATCHPAGE_NAME= "InputPatchPage"; //$NON-NLS-1$
private boolean fShowError= false;
private String fPatchSource;
private boolean fPatchRead= false;
private PatchWizard fPatchWizard;
private ActivationListener fActivationListener= new ActivationListener();
// SWT widgets
private Button fUseClipboardButton;
private Combo fPatchFileNameField;
private Button fPatchFileBrowseButton;
private Button fUsePatchFileButton;
private Button fUseWorkspaceButton;
private Button fUseURLButton;
private Combo fPatchURLField;
private Label fWorkspaceSelectLabel;
private TreeViewer fTreeViewer;
class ActivationListener extends ShellAdapter {
@Override
public void shellActivated(ShellEvent e) {
// allow error messages if the selected input actually has something selected in it
fShowError=true;
switch(getInputMethod()) {
case FILE:
fShowError= (fPatchFileNameField.getText() != ""); //$NON-NLS-1$
break;
case URL:
fShowError = (fPatchURLField.getText() != ""); //$NON-NLS-1$
break;
case WORKSPACE:
fShowError= (!fTreeViewer.getSelection().isEmpty());
break;
}
updateWidgetEnablements();
}
}
public InputPatchPage(PatchWizard pw) {
super(INPUTPATCHPAGE_NAME, PatchMessages.InputPatchPage_title, null);
fPatchWizard= pw;
setMessage(PatchMessages.InputPatchPage_message);
}
/*
* Get a path from the supplied text widget.
* @return org.eclipse.core.runtime.IPath
*/
protected IPath getPathFromText(Text textField) {
return (new Path(textField.getText())).makeAbsolute();
}
/* package */ String getPatchName() {
if (getInputMethod() == CLIPBOARD)
return PatchMessages.InputPatchPage_Clipboard;
return getPatchFilePath();
}
@Override
public void createControl(Composite parent) {
Composite composite= new Composite(parent, SWT.NULL);
composite.setLayout(new GridLayout());
composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));
setControl(composite);
initializeDialogUnits(parent);
buildPatchFileGroup(composite);
// by default, whatever was used last was selected or
// default to File if nothing has been selected
restoreWidgetValues();
// see if there are any better options presently selected (i.e workspace
// or clipboard or URL from clipboard)
adjustToCurrentTarget();
// No error for dialog opening
fShowError= false;
clearErrorMessage();
updateWidgetEnablements();
Shell shell= getShell();
shell.addShellListener(fActivationListener);
Dialog.applyDialogFont(composite);
PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, ICompareContextIds.PATCH_INPUT_WIZARD_PAGE);
}
/**
* Returns the next page depending on what type of patch is being applied:
* i) If the patch is a Workspace patch then it will proceed right to the PreviewPatchPage
* ii) If the patch is a single project patch then it will proceed to the PatchTargetPage, which
* allows the user to specify where to root the patch
* @return PreviewPatchPage if multi-project patch, PatchTargetPage if single project patch
*/
@Override
public IWizardPage getNextPage() {
if (!checkPageComplete())
return this;
WorkspacePatcher patcher= ((PatchWizard) getWizard()).getPatcher();
// guess prefix count
int guess= 0; // guessPrefix(diffs);
patcher.setStripPrefixSegments(guess);
// If this is a workspace patch we don't need to set a target as the targets will be figured out from
// all of the projects that make up the patch and continue on to final preview page
if (patcher.isWorkspacePatch()) {
// skip 'Patch Target' page
IWizardPage page = super.getNextPage();
if (page.getName().equals(PatchTargetPage.PATCHTARGETPAGE_NAME))
return page.getNextPage();
}
// If this is a git patch set the workspace root as the target and skip the target selection page
if (patcher.isGitPatch()) {
// skip 'Patch Target' page
IWizardPage page = super.getNextPage();
if (page.getName().equals(PatchTargetPage.PATCHTARGETPAGE_NAME)) {
// set the workspace root as the target
patcher.setTarget(ResourcesPlugin.getWorkspace().getRoot());
return page.getNextPage();
}
}
// else go on to target selection page
return super.getNextPage();
}
boolean checkPageComplete() {
WorkspacePatcher patcher= ((PatchWizard)getWizard()).getPatcher();
// Read in the patch
readInPatch();
IFilePatch2[] diffs= patcher.getDiffs();
if (diffs == null || diffs.length == 0) {
String format= PatchMessages.InputPatchPage_NoDiffsFound_format;
String message= MessageFormat.format(format, fPatchSource);
MessageDialog.openInformation(null, PatchMessages.InputPatchPage_PatchErrorDialog_title, message);
return false;
}
return true;
}
/*
* Reads in the patch contents
*/
public void readInPatch(){
if (fPatchRead)
return;
WorkspacePatcher patcher= ((PatchWizard) getWizard()).getPatcher();
// Create a reader for the input
Reader reader= null;
try {
int inputMethod= getInputMethod();
if (inputMethod == CLIPBOARD) {
Control c= getControl();
if (c != null) {
Clipboard clipboard= new Clipboard(c.getDisplay());
Object o= clipboard.getContents(TextTransfer.getInstance());
clipboard.dispose();
if (o instanceof String)
reader= new StringReader((String)o);
}
fPatchSource= PatchMessages.InputPatchPage_Clipboard_title;
} else if (inputMethod==FILE) {
String patchFilePath= getPatchFilePath();
if (patchFilePath != null) {
try {
reader= new FileReader(patchFilePath);
} catch (FileNotFoundException ex) {
MessageDialog.openError(null,
PatchMessages.InputPatchPage_PatchErrorDialog_title,
PatchMessages.InputPatchPage_PatchFileNotFound_message);
}
}
fPatchSource= PatchMessages.InputPatchPage_PatchFile_title;
} else if (inputMethod==URL) {
String patchFileURL = fPatchURLField.getText();
if (patchFileURL != null) {
try {
String contents = Utilities.getURLContents(new URL(
patchFileURL), getContainer());
if (contents != null)
reader = new StringReader(contents);
} catch (MalformedURLException | InvocationTargetException | OperationCanceledException | InterruptedException e) { // ignore
}
}
fPatchSource= PatchMessages.InputPatchPage_URL_title;
} else if (inputMethod==WORKSPACE) {
// Get the selected patch file (tree will only allow for one selection)
IResource[] resources= Utilities.getResources(fTreeViewer.getSelection());
IResource patchFile= resources[0];
if (patchFile != null) {
if (patchFile.getLocation() == null) {
MessageDialog.openError(null, PatchMessages.InputPatchPage_PatchErrorDialog_title, PatchMessages.InputPatchPage_PatchFileNotFound_message);
} else {
try {
reader = new FileReader(patchFile.getLocation().toFile());
} catch (FileNotFoundException ex) {
MessageDialog.openError(null, PatchMessages.InputPatchPage_PatchErrorDialog_title,
PatchMessages.InputPatchPage_PatchFileNotFound_message);
}
}
}
fPatchSource= PatchMessages.InputPatchPage_WorkspacePatch_title;
}
// parse the input
if (reader != null) {
try {
patcher.parse(new BufferedReader(reader));
//report back to the patch wizard that the patch has been read in
fPatchWizard.patchReadIn();
fPatchRead=true;
} catch (Exception ex) {
// Ignore. User will be informed of error since patcher contains no diffs
setPageComplete(false);
}
}
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException x) {
// silently ignored
}
}
}
}
@Override
public boolean canFlipToNextPage() {
// we can't call getNextPage to determine if flipping is allowed since computing
// the next page is quite expensive. So we say yes if the page is complete.
return isPageComplete();
}
private void setEnablePatchFile(boolean enable) {
fPatchFileNameField.setEnabled(enable);
fPatchFileBrowseButton.setEnabled(enable);
}
private void setEnableWorkspacePatch(boolean enable) {
fWorkspaceSelectLabel.setEnabled(enable);
fTreeViewer.getTree().setEnabled(enable);
}
private void setEnableURLPatch(boolean enable) {
fPatchURLField.setEnabled(enable);
}
/*
* Create the group for selecting the patch file
*/
private void buildPatchFileGroup(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));
// 1st row
GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalSpan= 3;
fUseClipboardButton= new Button(composite, SWT.RADIO);
fUseClipboardButton.setText(PatchMessages.InputPatchPage_UseClipboardButton_text);
fUseClipboardButton.setLayoutData(gd);
// 2nd row
fUsePatchFileButton= new Button(composite, SWT.RADIO);
fUsePatchFileButton.setText(PatchMessages.InputPatchPage_FileButton_text);
fPatchFileNameField= new Combo(composite, SWT.BORDER);
gd= new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint= SIZING_TEXT_FIELD_WIDTH;
fPatchFileNameField.setLayoutData(gd);
fPatchFileBrowseButton= new Button(composite, SWT.PUSH);
fPatchFileBrowseButton.setText(PatchMessages.InputPatchPage_ChooseFileButton_text);
GridData data= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
int widthHint= convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
Point minSize= fPatchFileBrowseButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
data.widthHint= Math.max(widthHint, minSize.x);
fPatchFileBrowseButton.setLayoutData(data);
//3rd row
fUseURLButton = new Button(composite, SWT.RADIO);
fUseURLButton.setText(PatchMessages.InputPatchPage_URLButton_text);
fPatchURLField = new Combo(composite, SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
fPatchURLField.setLayoutData(gd);
//4th row
fUseWorkspaceButton= new Button(composite, SWT.RADIO);
fUseWorkspaceButton.setText(PatchMessages.InputPatchPage_UseWorkspaceButton_text);
gd= new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
fUseWorkspaceButton.setLayoutData(gd);
addWorkspaceControls(parent);
// Add listeners
fUseClipboardButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (!fUseClipboardButton.getSelection())
return;
clearErrorMessage();
fShowError= true;
int state= getInputMethod();
setEnablePatchFile(state == FILE);
setEnableURLPatch(state == URL);
setEnableWorkspacePatch(state == WORKSPACE);
updateWidgetEnablements();
fPatchRead = false;
}
});
fUsePatchFileButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (!fUsePatchFileButton.getSelection())
return;
//If there is anything typed in at all
clearErrorMessage();
fShowError= (fPatchFileNameField.getText() != ""); //$NON-NLS-1$
int state= getInputMethod();
setEnablePatchFile(state == FILE);
setEnableURLPatch(state == URL);
setEnableWorkspacePatch(state == WORKSPACE);
updateWidgetEnablements();
fPatchRead = false;
}
});
fPatchFileNameField.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
updateWidgetEnablements();
}
});
fPatchFileNameField.addModifyListener(e -> {
clearErrorMessage();
fShowError= true;
fPatchRead = false;
updateWidgetEnablements();
});
fPatchFileBrowseButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
clearErrorMessage();
fShowError= true;
handlePatchFileBrowseButtonPressed();
updateWidgetEnablements();
}
});
fUseURLButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
clearErrorMessage();
fShowError= (fPatchURLField.getText() != ""); //$NON-NLS-1$
int state= getInputMethod();
setEnablePatchFile(state == FILE);
setEnableURLPatch(state == URL);
setEnableWorkspacePatch(state == WORKSPACE);
updateWidgetEnablements();
}
});
fPatchURLField.addModifyListener(e -> {
clearErrorMessage();
fShowError = true;
fPatchRead = false;
updateWidgetEnablements();
});
fUseWorkspaceButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (!fUseWorkspaceButton.getSelection())
return;
clearErrorMessage();
// If there is anything typed in at all
fShowError= (!fTreeViewer.getSelection().isEmpty());
int state= getInputMethod();
setEnablePatchFile(state == FILE);
setEnableURLPatch(state == URL);
setEnableWorkspacePatch(state == WORKSPACE);
updateWidgetEnablements();
fPatchRead = false;
}
});
fTreeViewer.addSelectionChangedListener(event -> {
clearErrorMessage();
updateWidgetEnablements();
});
fTreeViewer.addDoubleClickListener(event -> {
ISelection selection= event.getSelection();
if (selection instanceof TreeSelection) {
TreeSelection treeSel= (TreeSelection) selection;
Object res= treeSel.getFirstElement();
if (res != null) {
if (res instanceof IProject || res instanceof IFolder) {
if (fTreeViewer.getExpandedState(res))
fTreeViewer.collapseToLevel(res, 1);
else
fTreeViewer.expandToLevel(res, 1);
} else if (res instanceof IFile)
fPatchWizard.showPage(getNextPage());
}
}
});
}
private void addWorkspaceControls(Composite composite) {
Composite newComp= new Composite(composite, SWT.NONE);
GridLayout layout= new GridLayout(1, false);
layout.marginLeft= 16; // align w/ lable of check button
newComp.setLayout(layout);
newComp.setLayoutData(new GridData(GridData.FILL_BOTH));
fWorkspaceSelectLabel= new Label(newComp, SWT.LEFT);
fWorkspaceSelectLabel.setText(PatchMessages.InputPatchPage_WorkspaceSelectPatch_text);
fTreeViewer= new TreeViewer(newComp, SWT.BORDER);
GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
layoutData.heightHint = 300;
fTreeViewer.getTree().setLayoutData(layoutData);
fTreeViewer.setLabelProvider(new WorkbenchLabelProvider());
fTreeViewer.setContentProvider(new WorkbenchContentProvider());
fTreeViewer.setComparator(new ResourceComparator(ResourceComparator.NAME));
fTreeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot());
}
/**
* Updates the enable state of this page's controls.
*/
private void updateWidgetEnablements() {
String error= null;
boolean gotPatch= false;
int inputMethod= getInputMethod();
if (inputMethod==CLIPBOARD) {
Control c= getControl();
if (c != null) {
Clipboard clipboard= new Clipboard(c.getDisplay());
Object o= clipboard.getContents(TextTransfer.getInstance());
clipboard.dispose();
if (o instanceof String) {
String s= ((String) o).trim();
if (s.length() > 0)
gotPatch= true;
else
error= PatchMessages.InputPatchPage_ClipboardIsEmpty_message;
} else
error= PatchMessages.InputPatchPage_NoTextInClipboard_message;
} else
error= PatchMessages.InputPatchPage_CouldNotReadClipboard_message;
} else if (inputMethod==FILE) {
String path= fPatchFileNameField.getText();
if (path != null && path.length() > 0) {
File file= new File(path);
gotPatch= file.exists() && file.isFile() && file.length() > 0;
if (!gotPatch)
error= PatchMessages.InputPatchPage_CannotLocatePatch_message + path;
} else {
error= PatchMessages.InputPatchPage_NoFileName_message;
}
} else if (inputMethod == URL) {
String urlText = fPatchURLField.getText();
if(urlText != null) {
try {
new URL(urlText);
// Checking the URL is a bit too heavy for each keystroke.
// Let's assume it contains a valid patch.
gotPatch = true;
} catch (MalformedURLException e) {
error= PatchMessages.InputPatchPage_MalformedURL;
}
} else {
error= PatchMessages.InputPatchPage_NoURL;
}
} else if (inputMethod == WORKSPACE) {
//Get the selected patch file (tree will only allow for one selection)
IResource[] resources= Utilities.getResources(fTreeViewer.getSelection());
if (resources != null && resources.length > 0) {
IResource patchFile= resources[0];
if (patchFile != null && patchFile.getType() == IResource.FILE) {
IPath location = patchFile.getLocation();
if (location == null) {
error = PatchMessages.InputPatchPage_PatchFileNotFound_message;
} else {
File actualFile= location.toFile();
gotPatch= actualFile.exists()&&actualFile.isFile()&&actualFile.length() > 0;
if (!gotPatch)
error= PatchMessages.InputPatchPage_FileSelectedNotPatch_message;
}
}
} else {
error= PatchMessages.InputPatchPage_NoFileName_message;
}
}
setPageComplete(gotPatch);
if (fShowError)
setErrorMessage(error);
}
protected void handlePatchFileBrowseButtonPressed() {
FileDialog dialog= new FileDialog(getShell(), SWT.NONE);
dialog.setText(PatchMessages.InputPatchPage_SelectPatchFileDialog_title);
String patchFilePath= getPatchFilePath();
if (patchFilePath != null) {
int lastSegment= patchFilePath.lastIndexOf(File.separatorChar);
if (lastSegment > 0) {
patchFilePath= patchFilePath.substring(0, lastSegment);
}
}
dialog.setFilterPath(patchFilePath);
String res= dialog.open();
if (res == null)
return;
patchFilePath= dialog.getFileName();
IPath filterPath= new Path(dialog.getFilterPath());
IPath path= filterPath.append(patchFilePath).makeAbsolute();
patchFilePath= path.toOSString();
//fDialogSettings.put(IUIConstants.DIALOGSTORE_LASTEXTJAR, filterPath.toOSString());
fPatchFileNameField.setText(patchFilePath);
//setSourceName(patchFilePath);
}
/**
* Sets the source name of the import to be the supplied path.
* Adds the name of the path to the list of items in the
* source combo and selects it.
*
* @param path the path to be added
*/
protected void setSourceName(String path) {
if (path.length() > 0) {
String[] currentItems= fPatchFileNameField.getItems();
int selectionIndex= -1;
for (int i= 0; i < currentItems.length; i++)
if (currentItems[i].equals(path))
selectionIndex= i;
if (selectionIndex < 0) { // not found in history
int oldLength= currentItems.length;
String[] newItems= new String[oldLength + 1];
System.arraycopy(currentItems, 0, newItems, 0, oldLength);
newItems[oldLength]= path;
fPatchFileNameField.setItems(newItems);
selectionIndex= oldLength;
}
fPatchFileNameField.select(selectionIndex);
//resetSelection();
}
}
/**
* The Finish button was pressed. Try to do the required work now and answer
* a boolean indicating success. If false is returned then the wizard will
* not close.
*
* @return boolean
*/
public boolean finish() {
// if (!ensureSourceIsValid())
// return false;
saveWidgetValues();
// Iterator resourcesEnum= getSelectedResources().iterator();
// List fileSystemObjects= new ArrayList();
// while (resourcesEnum.hasNext()) {
// fileSystemObjects.add(
// ((FileSystemElement) resourcesEnum.next()).getFileSystemObject());
// }
//
// if (fileSystemObjects.size() > 0)
// return importResources(fileSystemObjects);
//
// MessageDialog
// .openInformation(
// getContainer().getShell(),
// DataTransferMessages.getString("DataTransfer.information"), //$NON-NLS-1$
// DataTransferMessages.getString("FileImport.noneSelected")); //$NON-NLS-1$
//
// return false;
return true;
}
/**
* Use the dialog store to restore widget values to the values that they held
* last time this wizard was used to completion
*/
private void restoreWidgetValues() {
int inputMethod= FILE;
IDialogSettings settings= getDialogSettings();
if (settings != null) {
try {
inputMethod= settings.getInt(STORE_INPUT_METHOD_ID);
} catch (NumberFormatException ex) {
//OK - no value stored in settings; just use CLIPBOARD
}
// set filenames history
String[] sourceNames= settings.getArray(STORE_PATCH_FILES_ID);
if (sourceNames != null)
for (String sourceName : sourceNames) {
if (sourceName != null && sourceName.length() > 0) {
fPatchFileNameField.add(sourceName);
}
}
// set patch file path
String patchFilePath= settings.get(STORE_PATCH_FILES_ID);
if (patchFilePath != null)
setSourceName(patchFilePath);
// set URLs history
String[] sourceURLs= settings.getArray(STORE_PATCH_URLS_ID);
if (sourceURLs != null)
for (String sourceURL : sourceURLs) {
if (sourceURL != null && sourceURL.length() > 0) {
fPatchURLField.add(sourceURL);
}
}
// If the previous apply patch was used with a clipboard, we need to check
// if there is a valid patch on the clipboard. This will be done in adjustToCurrentTarget()
// so just set it to FILE now and, if there exists a patch on the clipboard, then clipboard
// will be selected automatically
if (inputMethod == CLIPBOARD){
inputMethod= FILE;
fPatchFileNameField.deselectAll();
}
//set the workspace patch selection
String workspaceSetting= settings.get(STORE_WORKSPACE_PATH_ID);
if (workspaceSetting != null && workspaceSetting.length() > 0) {
// See if this resource still exists in the workspace
try {
IPath path= new Path(workspaceSetting);
IFile targetFile= ResourcesPlugin.getWorkspace().getRoot().getFile(path);
if (fTreeViewer != null && targetFile.exists()){
fTreeViewer.expandToLevel(targetFile, 0);
fTreeViewer.setSelection(new StructuredSelection(targetFile));
}
} catch (RuntimeException e) {
// Ignore. The setting was invalid
}
} else {
//check to see if the current input is set to workspace - if it is switch it
//back to clipboard since there is no corresponding element to go along with
//the tree viewer
if (inputMethod == WORKSPACE)
inputMethod= FILE;
}
}
// set radio buttons state
setInputButtonState(inputMethod);
}
/**
* Since Finish was pressed, write widget values to the dialog store so that they
* will persist into the next invocation of this wizard page
*/
void saveWidgetValues() {
IDialogSettings settings= getDialogSettings();
if (settings != null) {
settings.put(STORE_INPUT_METHOD_ID, getInputMethod());
settings.put(STORE_PATCH_FILES_ID, getPatchFilePath());
// update source names history
String[] sourceNames= settings.getArray(STORE_PATCH_FILES_ID);
if (sourceNames == null)
sourceNames= new String[0];
sourceNames= addToHistory(sourceNames, getPatchFilePath());
settings.put(STORE_PATCH_FILES_ID, sourceNames);
// update source URLs history
String[] sourceURLs= settings.getArray(STORE_PATCH_URLS_ID);
if (sourceURLs == null)
sourceURLs= new String[0];
sourceURLs= addToHistory(sourceURLs, fPatchURLField.getText());
settings.put(STORE_PATCH_URLS_ID, sourceURLs);
// save the workspace selection
settings.put(STORE_WORKSPACE_PATH_ID, getWorkspacePath());
}
}
private String getWorkspacePath() {
if (fTreeViewer != null){
IResource[] resources= Utilities.getResources(fTreeViewer.getSelection());
if (resources.length > 0) {
IResource patchFile= resources[0];
return patchFile.getFullPath().toString();
}
}
return ""; //$NON-NLS-1$
}
// static helpers
/**
* Checks to see if the file that has been selected for Apply Patch is
* actually a patch
*
* @return true if the file selected to run Apply Patch on in the workspace
* is a patch file or if the clipboard contains a patch or if the
* clipboard contains an URL (we assume it points to a patch )
*/
private boolean adjustToCurrentTarget() {
// readjust selection if there is a patch selected in the workspace or on the clipboard
// check workspace first
IResource patchTarget= fPatchWizard.getTarget();
if (patchTarget instanceof IFile && patchTarget.getLocation() != null) {
Reader reader= null;
try {
try {
reader= new FileReader(patchTarget.getLocation().toFile());
if (isPatchFile(reader)) {
// set choice to workspace
setInputButtonState(WORKSPACE);
if (fTreeViewer != null && patchTarget.exists()) {
fTreeViewer.expandToLevel(patchTarget, 0);
fTreeViewer.setSelection(new StructuredSelection(patchTarget));
}
return true;
}
} catch (FileNotFoundException ex) {
// silently ignored
}
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException x) {
// silently ignored
}
}
}
}
// check out clipboard contents
Reader reader = null;
Control c = getControl();
if (c != null) {
Clipboard clipboard= new Clipboard(c.getDisplay());
Object o= clipboard.getContents(TextTransfer.getInstance());
clipboard.dispose();
try {
if (o instanceof String) {
reader= new StringReader((String) o);
if (isPatchFile(reader)) {
setInputButtonState(CLIPBOARD);
return true;
}
// maybe it's an URL
try {
new URL((String)o);
setInputButtonState(URL);
fPatchURLField.setText((String)o);
return true;
} catch (MalformedURLException e) {
// ignore
}
}
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException x) {
// silently ignored
}
}
}
}
return false;
}
private boolean isPatchFile(Reader reader) {
WorkspacePatcher patcher= ((PatchWizard) getWizard()).getPatcher();
try {
patcher.parse(new BufferedReader(reader));
} catch (Exception ex) {
return false;
}
IFilePatch2[] diffs= patcher.getDiffs();
if (diffs == null || diffs.length == 0)
return false;
return true;
}
/*
* Clears the dialog message box
*/
private void clearErrorMessage(){
setErrorMessage(null);
}
private void setInputButtonState(int state) {
switch (state) {
case CLIPBOARD:
fUseClipboardButton.setSelection(true);
fUsePatchFileButton.setSelection(false);
fUseURLButton.setSelection(false);
fUseWorkspaceButton.setSelection(false);
break;
case FILE:
fUseClipboardButton.setSelection(false);
fUsePatchFileButton.setSelection(true);
fUseURLButton.setSelection(false);
fUseWorkspaceButton.setSelection(false);
break;
case URL:
fUseClipboardButton.setSelection(false);
fUsePatchFileButton.setSelection(false);
fUseURLButton.setSelection(true);
fUseWorkspaceButton.setSelection(false);
break;
case WORKSPACE:
fUseClipboardButton.setSelection(false);
fUsePatchFileButton.setSelection(false);
fUseURLButton.setSelection(false);
fUseWorkspaceButton.setSelection(true);
break;
}
setEnablePatchFile(state == FILE);
setEnableWorkspacePatch(state == WORKSPACE);
setEnableURLPatch(state == URL);
}
protected int getInputMethod() {
if (fUseClipboardButton.getSelection())
return CLIPBOARD;
if (fUsePatchFileButton.getSelection())
return FILE;
if(fUseURLButton.getSelection())
return URL;
return WORKSPACE;
}
private String getPatchFilePath() {
if (fPatchFileNameField != null)
return fPatchFileNameField.getText();
return ""; //$NON-NLS-1$
}
/*
* Adds an entry to a history, while taking care of duplicate history items
* and excessively long histories. The assumption is made that all histories
* should be of length <code>COMBO_HISTORY_LENGTH</code>.
*
* @param history the current history
* @param newEntry the entry to add to the history
*/
protected static String[] addToHistory(String[] history, String newEntry) {
ArrayList<String> l= new ArrayList<>(Arrays.asList(history));
l.remove(newEntry);
l.add(0,newEntry);
// since only one new item was added, we can be over the limit
// by at most one item
if (l.size() > COMBO_HISTORY_LENGTH)
l.remove(COMBO_HISTORY_LENGTH);
return l.toArray(new String[l.size()]);
}
public boolean isPatchRead() {
return fPatchRead;
}
}