From bc659bb75639e227c717f26a022cc99983ac9e7c Mon Sep 17 00:00:00 2001 From: Raphael Moll <> Date: Fri, 3 Apr 2009 13:32:32 -0700 Subject: [PATCH] AI 144486: ADT: Call the Extract String Refactoring to create a new XML String ID when selecting a string reference. BUG=1722971 Automated import of CL 144486 --- .../extractstring/ExtractStringInputPage.java | 390 ++++++++++++++++-- .../extractstring/ExtractStringRefactoring.java | 99 +++-- .../extractstring/XmlStringFileHelper.java} | 6 +- .../ide/eclipse/adt/ui/ReferenceChooserDialog.java | 36 +- .../adt/wizards/newstring/NewStringBaseImpl.java | 439 --------------------- .../adt/wizards/newstring/NewStringWizard.java | 66 ---- .../adt/wizards/newstring/NewStringWizardPage.java | 127 ------ 7 files changed, 461 insertions(+), 702 deletions(-) rename tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/{wizards/newstring/NewStringHelper.java => refactorings/extractstring/XmlStringFileHelper.java} (97%) delete mode 100644 tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringBaseImpl.java delete mode 100644 tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringWizard.java delete mode 100644 tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringWizardPage.java diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringInputPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringInputPage.java index 1f50c07b..7303b021 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringInputPage.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringInputPage.java @@ -17,34 +17,72 @@ package com.android.ide.eclipse.adt.refactorings.extractstring; -import com.android.ide.eclipse.adt.wizards.newstring.NewStringBaseImpl; -import com.android.ide.eclipse.adt.wizards.newstring.NewStringBaseImpl.INewStringPageCallback; -import com.android.ide.eclipse.adt.wizards.newstring.NewStringBaseImpl.ValidationStatus; +import com.android.ide.eclipse.adt.ui.ConfigurationSelector; +import com.android.ide.eclipse.common.AndroidConstants; +import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; +import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType; +import com.android.sdklib.SdkConstants; +import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardPage; import org.eclipse.ltk.ui.refactoring.UserInputWizardPage; 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.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; +import java.util.HashMap; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * @see ExtractStringRefactoring */ -class ExtractStringInputPage extends UserInputWizardPage - implements IWizardPage, INewStringPageCallback { +class ExtractStringInputPage extends UserInputWizardPage implements IWizardPage { + + /** Last res file path used, shared across the session instances but specific to the + * current project. The default for unknown projects is {@link #DEFAULT_RES_FILE_PATH}. */ + private static HashMap sLastResFilePath = new HashMap(); + + /** The project where the user selection happened. */ + private final IProject mProject; + + /** Test field where the user enters the new ID to be generated or replaced with. */ + private Text mStringIdField; + /** The configuration selector, to select the resource path of the XML file. */ + private ConfigurationSelector mConfigSelector; + /** The combo to display the existing XML files or enter a new one. */ + private Combo mResFileCombo; + + /** Regex pattern to read a valid res XML file path. It checks that the are 2 folders and + * a leaf file name ending with .xml */ + private static final Pattern RES_XML_FILE_REGEX = Pattern.compile( + "/res/[a-z][a-zA-Z0-9_-]+/[^.]+\\.xml"); //$NON-NLS-1$ + /** Absolute destination folder root, e.g. "/res/" */ + private static final String RES_FOLDER_ABS = + AndroidConstants.WS_RESOURCES + AndroidConstants.WS_SEP; + /** Relative destination folder root, e.g. "res/" */ + private static final String RES_FOLDER_REL = + SdkConstants.FD_RESOURCES + AndroidConstants.WS_SEP; + + private static final String DEFAULT_RES_FILE_PATH = "/res/values/strings.xml"; //$NON-NLS-1$ - private NewStringBaseImpl mImpl; + private XmlStringFileHelper mXmlHelper = new XmlStringFileHelper(); public ExtractStringInputPage(IProject project) { super("ExtractStringInputPage"); //$NON-NLS-1$ - mImpl = new NewStringBaseImpl(project, this); + mProject = project; } /** @@ -58,8 +96,11 @@ class ExtractStringInputPage extends UserInputWizardPage GridLayout layout = new GridLayout(); layout.numColumns = 1; content.setLayout(layout); + + createStringGroup(content); + createResFileGroup(content); - mImpl.createControl(content); + validatePage(); setControl(content); } @@ -68,15 +109,18 @@ class ExtractStringInputPage extends UserInputWizardPage * and by which options. * * @param content A composite with a 1-column grid layout - * @return The {@link Text} field for the new String ID name. */ - public Text createStringGroup(Composite content) { + public void createStringGroup(Composite content) { final ExtractStringRefactoring ref = getOurRefactoring(); Group group = new Group(content, SWT.NONE); group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - group.setText("String Replacement"); + if (ref.getMode() == ExtractStringRefactoring.Mode.EDIT_SOURCE) { + group.setText("String Replacement"); + } else { + group.setText("New String"); + } GridLayout layout = new GridLayout(); layout.numColumns = 2; @@ -85,7 +129,7 @@ class ExtractStringInputPage extends UserInputWizardPage // line: Textfield for string value (based on selection, if any) Label label = new Label(group, SWT.NONE); - label.setText("String:"); + label.setText("String"); String selectedString = ref.getTokenString(); @@ -97,7 +141,7 @@ class ExtractStringInputPage extends UserInputWizardPage stringValueField.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { - if (mImpl.validatePage()) { + if (validatePage()) { ref.setNewStringValue(stringValueField.getText()); } } @@ -110,23 +154,76 @@ class ExtractStringInputPage extends UserInputWizardPage // line : Textfield for new ID label = new Label(group, SWT.NONE); - label.setText("Replace by R.string."); + if (ref.getMode() == ExtractStringRefactoring.Mode.EDIT_SOURCE) { + label.setText("Replace by R.string."); + } else if (ref.getMode() == ExtractStringRefactoring.Mode.SELECT_NEW_ID) { + label.setText("New R.string."); + } else { + label.setText("ID R.string."); + } - final Text stringIdField = new Text(group, SWT.SINGLE | SWT.LEFT | SWT.BORDER); - stringIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - stringIdField.setText(guessId(selectedString)); + mStringIdField = new Text(group, SWT.SINGLE | SWT.LEFT | SWT.BORDER); + mStringIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + mStringIdField.setText(guessId(selectedString)); - ref.setNewStringId(stringIdField.getText().trim()); + ref.setNewStringId(mStringIdField.getText().trim()); - stringIdField.addModifyListener(new ModifyListener() { + mStringIdField.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { - if (mImpl.validatePage()) { - ref.setNewStringId(stringIdField.getText().trim()); + if (validatePage()) { + ref.setNewStringId(mStringIdField.getText().trim()); } } }); + } + + /** + * Creates the lower group with the fields to choose the resource confirmation and + * the target XML file. + * + * @param content A composite with a 1-column grid layout + */ + private void createResFileGroup(Composite content) { + + Group group = new Group(content, SWT.NONE); + group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + group.setText("XML resource to edit"); + + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + group.setLayout(layout); + + // line: selection of the res config + + Label label; + label = new Label(group, SWT.NONE); + label.setText("Configuration:"); + + mConfigSelector = new ConfigurationSelector(group); + GridData gd = new GridData(2, GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL); + gd.widthHint = ConfigurationSelector.WIDTH_HINT; + gd.heightHint = ConfigurationSelector.HEIGHT_HINT; + mConfigSelector.setLayoutData(gd); + OnConfigSelectorUpdated onConfigSelectorUpdated = new OnConfigSelectorUpdated(); + mConfigSelector.setOnChangeListener(onConfigSelectorUpdated); + + // line: selection of the output file + + label = new Label(group, SWT.NONE); + label.setText("Resource file:"); + + mResFileCombo = new Combo(group, SWT.DROP_DOWN); + mResFileCombo.select(0); + mResFileCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + mResFileCombo.addModifyListener(onConfigSelectorUpdated); + + // set output file name to the last one used + + String projPath = mProject.getFullPath().toPortableString(); + String filePath = sLastResFilePath.get(projPath); - return stringIdField; + mResFileCombo.setText(filePath != null ? filePath : DEFAULT_RES_FILE_PATH); + onConfigSelectorUpdated.run(); } /** @@ -157,8 +254,251 @@ class ExtractStringInputPage extends UserInputWizardPage return (ExtractStringRefactoring) getRefactoring(); } - public void postValidatePage(ValidationStatus status) { - ExtractStringRefactoring ref = getOurRefactoring(); - ref.setTargetFile(mImpl.getResFileProjPath()); + /** + * Validates fields of the wizard input page. Displays errors as appropriate and + * enable the "Next" button (or not) by calling {@link #setPageComplete(boolean)}. + * + * @return True if the page has been positively validated. It may still have warnings. + */ + private boolean validatePage() { + boolean success = true; + + // Analyze fatal errors. + + String text = mStringIdField.getText().trim(); + if (text == null || text.length() < 1) { + setErrorMessage("Please provide a resource ID."); + success = false; + } else { + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + boolean ok = i == 0 ? + Character.isJavaIdentifierStart(c) : + Character.isJavaIdentifierPart(c); + if (!ok) { + setErrorMessage(String.format( + "The resource ID must be a valid Java identifier. The character %1$c at position %2$d is not acceptable.", + c, i+1)); + success = false; + break; + } + } + } + + String resFile = mResFileCombo.getText(); + if (success) { + if (resFile == null || resFile.length() == 0) { + setErrorMessage("A resource file name is required."); + success = false; + } else if (!RES_XML_FILE_REGEX.matcher(resFile).matches()) { + setErrorMessage("The XML file name is not valid."); + success = false; + } + } + + // Analyze info & warnings. + + if (success) { + setErrorMessage(null); + + ExtractStringRefactoring ref = getOurRefactoring(); + + ref.setTargetFile(resFile); + sLastResFilePath.put(mProject.getFullPath().toPortableString(), resFile); + + if (mXmlHelper.isResIdDuplicate(mProject, resFile, text)) { + String msg = String.format("There's already a string item called '%1$s' in %2$s.", + text, resFile); + if (ref.getMode() == ExtractStringRefactoring.Mode.SELECT_NEW_ID) { + setErrorMessage(msg); + success = false; + } else { + setMessage(msg, WizardPage.WARNING); + } + } else if (mProject.findMember(resFile) == null) { + setMessage( + String.format("File %2$s does not exist and will be created.", + text, resFile), + WizardPage.INFORMATION); + } else { + setMessage(null); + } + } + + setPageComplete(success); + return success; + } + + public class OnConfigSelectorUpdated implements Runnable, ModifyListener { + + /** Regex pattern to parse a valid res path: it reads (/res/folder-name/)+(filename). */ + private final Pattern mPathRegex = Pattern.compile( + "(/res/[a-z][a-zA-Z0-9_-]+/)(.+)"); //$NON-NLS-1$ + + /** Temporary config object used to retrieve the Config Selector value. */ + private FolderConfiguration mTempConfig = new FolderConfiguration(); + + private HashMap> mFolderCache = + new HashMap>(); + private String mLastFolderUsedInCombo = null; + private boolean mInternalConfigChange; + private boolean mInternalFileComboChange; + + /** + * Callback invoked when the {@link ConfigurationSelector} has been changed. + *

+ * The callback does the following: + *

    + *
  • Examine the current file name to retrieve the XML filename, if any. + *
  • Recompute the path based on the configuration selector (e.g. /res/values-fr/). + *
  • Examine the path to retrieve all the files in it. Keep those in a local cache. + *
  • If the XML filename from step 1 is not in the file list, it's a custom file name. + * Insert it and sort it. + *
  • Re-populate the file combo with all the choices. + *
  • Select the original XML file. + */ + public void run() { + if (mInternalConfigChange) { + return; + } + + // get current leafname, if any + String leafName = ""; //$NON-NLS-1$ + String currPath = mResFileCombo.getText(); + Matcher m = mPathRegex.matcher(currPath); + if (m.matches()) { + // Note: groups 1 and 2 cannot be null. + leafName = m.group(2); + currPath = m.group(1); + } else { + // There was a path but it was invalid. Ignore it. + currPath = ""; //$NON-NLS-1$ + } + + // recreate the res path from the current configuration + mConfigSelector.getConfiguration(mTempConfig); + StringBuffer sb = new StringBuffer(RES_FOLDER_ABS); + sb.append(mTempConfig.getFolderName(ResourceFolderType.VALUES)); + sb.append('/'); + + String newPath = sb.toString(); + if (newPath.equals(currPath) && newPath.equals(mLastFolderUsedInCombo)) { + // Path has not changed. No need to reload. + return; + } + + // Get all the files at the new path + + TreeSet filePaths = mFolderCache.get(newPath); + + if (filePaths == null) { + filePaths = new TreeSet(); + + IFolder folder = mProject.getFolder(newPath); + if (folder != null && folder.exists()) { + try { + for (IResource res : folder.members()) { + String name = res.getName(); + if (res.getType() == IResource.FILE && name.endsWith(".xml")) { + filePaths.add(newPath + name); + } + } + } catch (CoreException e) { + // Ignore. + } + } + + mFolderCache.put(newPath, filePaths); + } + + currPath = newPath + leafName; + if (leafName.length() > 0 && !filePaths.contains(currPath)) { + filePaths.add(currPath); + } + + // Fill the combo + try { + mInternalFileComboChange = true; + + mResFileCombo.removeAll(); + + for (String filePath : filePaths) { + mResFileCombo.add(filePath); + } + + int index = -1; + if (leafName.length() > 0) { + index = mResFileCombo.indexOf(currPath); + if (index >= 0) { + mResFileCombo.select(index); + } + } + + if (index == -1) { + mResFileCombo.setText(currPath); + } + + mLastFolderUsedInCombo = newPath; + + } finally { + mInternalFileComboChange = false; + } + + // finally validate the whole page + validatePage(); + } + + /** + * Callback invoked when {@link ExtractStringInputPage#mResFileCombo} has been + * modified. + */ + public void modifyText(ModifyEvent e) { + if (mInternalFileComboChange) { + return; + } + + String wsFolderPath = mResFileCombo.getText(); + + // This is a custom path, we need to sanitize it. + // First it should start with "/res/". Then we need to make sure there are no + // relative paths, things like "../" or "./" or even "//". + wsFolderPath = wsFolderPath.replaceAll("/+\\.\\./+|/+\\./+|//+|\\\\+|^/+", "/"); //$NON-NLS-1$ //$NON-NLS-2$ + wsFolderPath = wsFolderPath.replaceAll("^\\.\\./+|^\\./+", ""); //$NON-NLS-1$ //$NON-NLS-2$ + wsFolderPath = wsFolderPath.replaceAll("/+\\.\\.$|/+\\.$|/+$", ""); //$NON-NLS-1$ //$NON-NLS-2$ + + // We get "res/foo" from selections relative to the project when we want a "/res/foo" path. + if (wsFolderPath.startsWith(RES_FOLDER_REL)) { + wsFolderPath = RES_FOLDER_ABS + wsFolderPath.substring(RES_FOLDER_REL.length()); + + mInternalFileComboChange = true; + mResFileCombo.setText(wsFolderPath); + mInternalFileComboChange = false; + } + + if (wsFolderPath.startsWith(RES_FOLDER_ABS)) { + wsFolderPath = wsFolderPath.substring(RES_FOLDER_ABS.length()); + + int pos = wsFolderPath.indexOf(AndroidConstants.WS_SEP_CHAR); + if (pos >= 0) { + wsFolderPath = wsFolderPath.substring(0, pos); + } + + String[] folderSegments = wsFolderPath.split(FolderConfiguration.QUALIFIER_SEP); + + if (folderSegments.length > 0) { + String folderName = folderSegments[0]; + + if (folderName != null && !folderName.equals(wsFolderPath)) { + // update config selector + mInternalConfigChange = true; + mConfigSelector.setConfiguration(folderSegments); + mInternalConfigChange = false; + } + } + } + + validatePage(); + } } + } diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringRefactoring.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringRefactoring.java index a17d8179..8a38e526 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringRefactoring.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/ExtractStringRefactoring.java @@ -16,7 +16,6 @@ package com.android.ide.eclipse.adt.refactorings.extractstring; -import com.android.ide.eclipse.adt.wizards.newstring.NewStringHelper; import com.android.ide.eclipse.common.AndroidConstants; import com.android.ide.eclipse.common.project.AndroidManifestParser; @@ -98,8 +97,8 @@ import java.util.Map; *
  • On success, the wizard is shown, which let the user input the new ID to use. *
  • The wizard sets the user input values into this refactoring instance, e.g. the new string * ID, the XML file to update, etc. The wizard does use the utility method - * {@link NewStringHelper#isResIdDuplicate(IProject, String, String)} to check whether the new - * ID is already defined in the target XML file. + * {@link XmlStringFileHelper#isResIdDuplicate(IProject, String, String)} to check whether + * the new ID is already defined in the target XML file. *
  • Once Preview or Finish is selected in the wizard, the * {@link #checkFinalConditions(IProgressMonitor)} is called to double-check the user input * and compute the actual changes. @@ -122,10 +121,23 @@ import java.util.Map; */ public class ExtractStringRefactoring extends Refactoring { - private enum Mode { + public enum Mode { + /** + * the Extract String refactoring is called on an existing source file. + * Its purpose is then to get the selected string of the source and propose to + * change it by an XML id. The XML id may be a new one or an existing one. + */ EDIT_SOURCE, - MAKE_ID, - MAKE_NEW_ID + /** + * The Extract String refactoring is called without any source file. + * Its purpose is then to create a new XML string ID or select/modify an existing one. + */ + SELECT_ID, + /** + * The Extract String refactoring is called without any source file. + * Its purpose is then to create a new XML string ID. The ID must not already exist. + */ + SELECT_NEW_ID } /** The {@link Mode} of operation of the refactoring. */ @@ -133,6 +145,8 @@ public class ExtractStringRefactoring extends Refactoring { /** The file model being manipulated. * Value is null when not on {@link Mode#EDIT_SOURCE} mode. */ private final IFile mFile; + /** The project that contains {@link #mFile} and that contains the target XML file to modify. */ + private final IProject mProject; /** The start of the selection in {@link #mFile}. * Value is -1 when not on {@link Mode#EDIT_SOURCE} mode. */ private final int mSelectionStart; @@ -157,19 +171,30 @@ public class ExtractStringRefactoring extends Refactoring { /** The list of changes computed by {@link #checkFinalConditions(IProgressMonitor)} and * used by {@link #createChange(IProgressMonitor)}. */ private ArrayList mChanges; - - private NewStringHelper mHelper = new NewStringHelper(); + + private XmlStringFileHelper mXmlHelper = new XmlStringFileHelper(); + + private static final String KEY_MODE = "mode"; //$NON-NLS-1$ + private static final String KEY_FILE = "file"; //$NON-NLS-1$ + private static final String KEY_PROJECT = "proj"; //$NON-NLS-1$ + private static final String KEY_SEL_START = "sel-start"; //$NON-NLS-1$ + private static final String KEY_SEL_END = "sel-end"; //$NON-NLS-1$ + private static final String KEY_TOK_ESC = "tok-esc"; //$NON-NLS-1$ public ExtractStringRefactoring(Map arguments) throws NullPointerException { - mMode = Mode.valueOf(arguments.get("mode")); //$NON-NLS-1$ + mMode = Mode.valueOf(arguments.get(KEY_MODE)); + + IPath path = Path.fromPortableString(arguments.get(KEY_PROJECT)); + mProject = (IProject) ResourcesPlugin.getWorkspace().getRoot().findMember(path); if (mMode == Mode.EDIT_SOURCE) { - IPath path = Path.fromPortableString(arguments.get("file")); //$NON-NLS-1$ + path = Path.fromPortableString(arguments.get(KEY_FILE)); mFile = (IFile) ResourcesPlugin.getWorkspace().getRoot().findMember(path); - mSelectionStart = Integer.parseInt(arguments.get("sel-start")); //$NON-NLS-1$ - mSelectionEnd = Integer.parseInt(arguments.get("sel-end")); //$NON-NLS-1$ - mTokenString = arguments.get("tok-esc"); //$NON-NLS-1$ + + mSelectionStart = Integer.parseInt(arguments.get(KEY_SEL_START)); + mSelectionEnd = Integer.parseInt(arguments.get(KEY_SEL_END)); + mTokenString = arguments.get(KEY_TOK_ESC); } else { mFile = null; mSelectionStart = mSelectionEnd = -1; @@ -179,12 +204,13 @@ public class ExtractStringRefactoring extends Refactoring { private Map createArgumentMap() { HashMap args = new HashMap(); - args.put("mode", mMode.name()); //$NON-NLS-1$ + args.put(KEY_MODE, mMode.name()); + args.put(KEY_PROJECT, mProject.getFullPath().toPortableString()); if (mMode == Mode.EDIT_SOURCE) { - args.put("file", mFile.getFullPath().toPortableString()); //$NON-NLS-1$ - args.put("sel-start", Integer.toString(mSelectionStart)); //$NON-NLS-1$ - args.put("sel-end", Integer.toString(mSelectionEnd)); //$NON-NLS-1$ - args.put("tok-esc", mTokenString); //$NON-NLS-1$ + args.put(KEY_FILE, mFile.getFullPath().toPortableString()); + args.put(KEY_SEL_START, Integer.toString(mSelectionStart)); + args.put(KEY_SEL_END, Integer.toString(mSelectionEnd)); + args.put(KEY_TOK_ESC, mTokenString); } return args; } @@ -201,6 +227,7 @@ public class ExtractStringRefactoring extends Refactoring { public ExtractStringRefactoring(IFile file, ITextSelection selection) { mMode = Mode.EDIT_SOURCE; mFile = file; + mProject = file.getProject(); mSelectionStart = selection.getOffset(); mSelectionEnd = mSelectionStart + Math.max(0, selection.getLength() - 1); } @@ -209,25 +236,35 @@ public class ExtractStringRefactoring extends Refactoring { * Constructor to use when the Extract String refactoring is called without * any source file. Its purpose is then to create a new XML string ID. * + * @param project The project where the target XML file to modify is located. Cannot be null. * @param enforceNew If true the XML ID must be a new one. If false, an existing ID can be * used. */ - public ExtractStringRefactoring(boolean enforceNew) { - mMode = enforceNew ? Mode.MAKE_NEW_ID : Mode.MAKE_ID; + public ExtractStringRefactoring(IProject project, boolean enforceNew) { + mMode = enforceNew ? Mode.SELECT_NEW_ID : Mode.SELECT_ID; mFile = null; + mProject = project; mSelectionStart = mSelectionEnd = -1; } - - /** * @see org.eclipse.ltk.core.refactoring.Refactoring#getName() */ @Override public String getName() { + if (mMode == Mode.SELECT_ID) { + return "Create or USe Android String"; + } else if (mMode == Mode.SELECT_NEW_ID) { + return "Create New Android String"; + } + return "Extract Android String"; } + public Mode getMode() { + return mMode; + } + /** * Gets the actual string selected, after UTF characters have been escaped, * good for display. @@ -236,6 +273,10 @@ public class ExtractStringRefactoring extends Refactoring { return mTokenString; } + public String getXmlStringId() { + return mXmlStringId; + } + /** * Step 1 of 3 of the refactoring: * Checks that the current selection meets the initial condition before the ExtractString @@ -459,7 +500,7 @@ public class ExtractStringRefactoring extends Refactoring { // Prepare the change for the XML file. - if (!mHelper.isResIdDuplicate(mFile.getProject(), mTargetXmlFileWsPath, mXmlStringId)) { + if (!mXmlHelper.isResIdDuplicate(mProject, mTargetXmlFileWsPath, mXmlStringId)) { // We actually change it only if the ID doesn't exist yet Change change = createXmlChange((IFile) targetXml, mXmlStringId, mXmlStringValue, status, SubMonitor.convert(monitor, 1)); @@ -525,7 +566,7 @@ public class ExtractStringRefactoring extends Refactoring { content.append("\n"); //$NON-NLS-1$ edit = new InsertEdit(0, content.toString()); - editGroup = new TextEditGroup("Create ID in new XML file", edit); + editGroup = new TextEditGroup("Create in new XML file", edit); } else { // The file exist. Attempt to parse it as a valid XML document. try { @@ -556,7 +597,7 @@ public class ExtractStringRefactoring extends Refactoring { } edit = new ReplaceEdit(offset, len, content.toString()); - editGroup = new TextEditGroup("Insert ID in XML file", edit); + editGroup = new TextEditGroup("Insert in XML file", edit); } } catch (CoreException e) { // Failed to read file. Ignore. Will return null below. @@ -702,8 +743,7 @@ public class ExtractStringRefactoring extends Refactoring { // the FQCN of the R class. String packageName = null; String error = null; - IProject proj = unit.getJavaProject().getProject(); - IResource manifestFile = proj.findMember(AndroidConstants.FN_ANDROID_MANIFEST); + IResource manifestFile = mProject.findMember(AndroidConstants.FN_ANDROID_MANIFEST); if (manifestFile == null || manifestFile.getType() != IResource.FILE) { error = "File not found"; } else { @@ -895,7 +935,7 @@ public class ExtractStringRefactoring extends Refactoring { mXmlStringId); ExtractStringDescriptor desc = new ExtractStringDescriptor( - mUnit.getJavaProject().getElementName(), //project + mProject.getName(), //project comment, //description comment, //comment createArgumentMap()); @@ -919,8 +959,7 @@ public class ExtractStringRefactoring extends Refactoring { * compilation unit. The resource may not exist. */ private IResource getTargetXmlResource(String xmlFileWsPath) { - IProject proj = mFile.getProject(); - IResource resource = proj.getFile(xmlFileWsPath); + IResource resource = mProject.getFile(xmlFileWsPath); return resource; } diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringHelper.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/XmlStringFileHelper.java similarity index 97% rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringHelper.java rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/XmlStringFileHelper.java index 3b839271..6c8bbdbd 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringHelper.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/refactorings/extractstring/XmlStringFileHelper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.ide.eclipse.adt.wizards.newstring; +package com.android.ide.eclipse.adt.refactorings.extractstring; import com.android.ide.eclipse.common.project.AndroidXPathFactory; @@ -35,7 +35,7 @@ import javax.xml.xpath.XPathExpressionException; /** * */ -public class NewStringHelper { +class XmlStringFileHelper { /** A temporary cache of R.string IDs defined by a given xml file. The key is the * project path of the file, the data is a set of known string Ids for that file. */ @@ -43,7 +43,7 @@ public class NewStringHelper { /** An instance of XPath, created lazily on demand. */ private XPath mXPath; - public NewStringHelper() { + public XmlStringFileHelper() { } /** diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/ui/ReferenceChooserDialog.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/ui/ReferenceChooserDialog.java index 031b3038..966c5c81 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/ui/ReferenceChooserDialog.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/ui/ReferenceChooserDialog.java @@ -70,6 +70,7 @@ public class ReferenceChooserDialog extends SelectionStatusDialog { private FilteredTree mFilteredTree; private Button mNewResButton; private final IProject mProject; + private TreeViewer mTreeViewer; /** * @param project @@ -159,8 +160,8 @@ public class ReferenceChooserDialog extends SelectionStatusDialog { mFilteredTree.setLayoutData(data); mFilteredTree.setFont(parent.getFont()); - TreeViewer treeViewer = mFilteredTree.getViewer(); - Tree tree = treeViewer.getTree(); + mTreeViewer = mFilteredTree.getViewer(); + Tree tree = mTreeViewer.getTree(); tree.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { @@ -172,9 +173,9 @@ public class ReferenceChooserDialog extends SelectionStatusDialog { } }); - treeViewer.setLabelProvider(new ResourceLabelProvider()); - treeViewer.setContentProvider(new ResourceContentProvider(false /* fullLevels */)); - treeViewer.setInput(mResources); + mTreeViewer.setLabelProvider(new ResourceLabelProvider()); + mTreeViewer.setContentProvider(new ResourceContentProvider(false /* fullLevels */)); + mTreeViewer.setInput(mResources); } protected void handleSelection() { @@ -242,8 +243,10 @@ public class ReferenceChooserDialog extends SelectionStatusDialog { // We only support adding new strings right now mNewResButton.setEnabled(type == ResourceType.STRING); - String title = String.format("New %1$s", type == null ? "Resource" : type.getDisplayName()); + String title = String.format("New %1$s...", + type == null ? "Resource" : type.getDisplayName()); mNewResButton.setText(title); + mNewResButton.pack(); } /** @@ -259,14 +262,19 @@ public class ReferenceChooserDialog extends SelectionStatusDialog { // We currently only support strings if (type == ResourceType.STRING) { - ExtractStringRefactoring ref = new ExtractStringRefactoring(true /*enforceNew*/); + ExtractStringRefactoring ref = new ExtractStringRefactoring( + mProject, true /*enforceNew*/); RefactoringWizard wizard = new ExtractStringWizard(ref, mProject); RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard); try { IWorkbench w = PlatformUI.getWorkbench(); - op.run(w.getDisplay().getActiveShell(), wizard.getDefaultPageTitle()); - - // TODO Select string + if (op.run(w.getDisplay().getActiveShell(), wizard.getDefaultPageTitle()) == + IDialogConstants.OK_ID) { + mTreeViewer.refresh(); + + // select it if possible + setupInitialSelection(type, ref.getXmlStringId()); + } } catch (InterruptedException ex) { // Interrupted. Pass. } @@ -335,7 +343,9 @@ public class ReferenceChooserDialog extends SelectionStatusDialog { if (resourceName.equals(resourceItem.getName())) { // name of the resource match, we select it, TreePath treePath = new TreePath(new Object[] { resourceType, resourceItem }); - mFilteredTree.getViewer().setSelection(new TreeSelection(treePath)); + mFilteredTree.getViewer().setSelection( + new TreeSelection(treePath), + true /*reveal*/); // and we're done. return; @@ -345,7 +355,9 @@ public class ReferenceChooserDialog extends SelectionStatusDialog { // if we get here, the resource type is valid, but the resource is missing. // we select and expand the resource type element. TreePath treePath = new TreePath(new Object[] { resourceType }); - mFilteredTree.getViewer().setSelection(new TreeSelection(treePath)); + mFilteredTree.getViewer().setSelection( + new TreeSelection(treePath), + true /*reveal*/); mFilteredTree.getViewer().setExpandedState(resourceType, true /* expanded */); } } diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringBaseImpl.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringBaseImpl.java deleted file mode 100644 index 334b1338..00000000 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringBaseImpl.java +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.wizards.newstring; - - -import com.android.ide.eclipse.adt.ui.ConfigurationSelector; -import com.android.ide.eclipse.common.AndroidConstants; -import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; -import com.android.ide.eclipse.editors.resources.manager.ResourceFolderType; -import com.android.sdklib.SdkConstants; - -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.jface.wizard.WizardPage; -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.Combo; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -import java.util.HashMap; -import java.util.TreeSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class NewStringBaseImpl { - - public interface INewStringPageCallback { - /** - * Creates the top group with the field to replace which string and by what - * and by which options. - * - * @param content A composite with a 1-column grid layout - * @return The {@link Text} field for the new String ID name. - */ - public Text createStringGroup(Composite content); - - /** Implements {@link WizardPage#setErrorMessage(String)} */ - public void setErrorMessage(String newMessage); - /** Implements {@link WizardPage#setMessage(String, int)} */ - public void setMessage(String msg, int type); - /** Implements {@link WizardPage#setPageComplete(boolean)} */ - public void setPageComplete(boolean success); - - public void postValidatePage(ValidationStatus status); - } - - public class ValidationStatus { - private String mError = null; - private String mMessage = null; - public int mMessageType = WizardPage.NONE; - - public boolean success() { - return getError() != null; - } - - public void setError(String error) { - mError = error; - mMessageType = WizardPage.ERROR; - } - - public String getError() { - return mError; - } - - public void setMessage(String msg, int type) { - mMessage = msg; - mMessageType = type; - } - - public String getMessage() { - return mMessage; - } - - public int getMessageType() { - return mMessageType; - } - } - - /** Last res file path used, shared across the session instances but specific to the - * current project. The default for unknown projects is {@link #DEFAULT_RES_FILE_PATH}. */ - private static HashMap sLastResFilePath = new HashMap(); - - /** The project where the user selection happened. */ - private final IProject mProject; - /** Text field where the user enters the new ID. */ - private Text mStringIdField; - /** The configuration selector, to select the resource path of the XML file. */ - private ConfigurationSelector mConfigSelector; - /** The combo to display the existing XML files or enter a new one. */ - private Combo mResFileCombo; - - private NewStringHelper mHelper = new NewStringHelper(); - - /** Regex pattern to read a valid res XML file path. It checks that the are 2 folders and - * a leaf file name ending with .xml */ - private static final Pattern RES_XML_FILE_REGEX = Pattern.compile( - "/res/[a-z][a-zA-Z0-9_-]+/[^.]+\\.xml"); //$NON-NLS-1$ - /** Absolute destination folder root, e.g. "/res/" */ - private static final String RES_FOLDER_ABS = - AndroidConstants.WS_RESOURCES + AndroidConstants.WS_SEP; - /** Relative destination folder root, e.g. "res/" */ - private static final String RES_FOLDER_REL = - SdkConstants.FD_RESOURCES + AndroidConstants.WS_SEP; - - private static final String DEFAULT_RES_FILE_PATH = "/res/values/strings.xml"; //$NON-NLS-1$ - - private final INewStringPageCallback mWizardPage; - - public NewStringBaseImpl(IProject project, INewStringPageCallback wizardPage) { - mProject = project; - mWizardPage = wizardPage; - } - - /** - * Create the UI for the new string wizard. - */ - public void createControl(Composite parent) { - mStringIdField = mWizardPage.createStringGroup(parent); - createResFileGroup(parent); - } - - /** - * Creates the lower group with the fields to choose the resource confirmation and - * the target XML file. - * - * @param content A composite with a 1-column grid layout - */ - private void createResFileGroup(Composite content) { - - Group group = new Group(content, SWT.NONE); - group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - group.setText("XML resource to edit"); - - GridLayout layout = new GridLayout(); - layout.numColumns = 2; - group.setLayout(layout); - - // line: selection of the res config - - Label label; - label = new Label(group, SWT.NONE); - label.setText("Configuration:"); - - mConfigSelector = new ConfigurationSelector(group); - GridData gd = new GridData(2, GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL); - gd.widthHint = ConfigurationSelector.WIDTH_HINT; - gd.heightHint = ConfigurationSelector.HEIGHT_HINT; - mConfigSelector.setLayoutData(gd); - OnConfigSelectorUpdated onConfigSelectorUpdated = new OnConfigSelectorUpdated(); - mConfigSelector.setOnChangeListener(onConfigSelectorUpdated); - - // line: selection of the output file - - label = new Label(group, SWT.NONE); - label.setText("Resource file:"); - - mResFileCombo = new Combo(group, SWT.DROP_DOWN); - mResFileCombo.select(0); - mResFileCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mResFileCombo.addModifyListener(onConfigSelectorUpdated); - - // set output file name to the last one used - - String projPath = mProject.getFullPath().toPortableString(); - String filePath = sLastResFilePath.get(projPath); - - mResFileCombo.setText(filePath != null ? filePath : DEFAULT_RES_FILE_PATH); - onConfigSelectorUpdated.run(); - } - - /** - * Validates fields of the wizard input page. Displays errors as appropriate and - * enable the "Next" button (or not) by calling - * {@link INewStringPageCallback#setPageComplete(boolean)}. - * - * @return True if the page has been positively validated. It may still have warnings. - */ - public boolean validatePage() { - ValidationStatus status = new ValidationStatus(); - - validateStringFields(status); - if (status.success()) { - validatePathFields(status); - } - - mWizardPage.postValidatePage(status); - - mWizardPage.setErrorMessage(status.getError()); - mWizardPage.setMessage(status.getMessage(), status.getMessageType()); - mWizardPage.setPageComplete(status.success()); - return status.success(); - } - - public void validateStringFields(ValidationStatus status) { - - String text = mStringIdField.getText().trim(); - if (text == null || text.length() < 1) { - status.setError("Please provide a resource ID to replace with."); - } else { - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - boolean ok = i == 0 ? - Character.isJavaIdentifierStart(c) : - Character.isJavaIdentifierPart(c); - if (!ok) { - status.setError(String.format( - "The resource ID must be a valid Java identifier. The character %1$c at position %2$d is not acceptable.", - c, i+1)); - break; - } - } - } - } - - public ValidationStatus validatePathFields(ValidationStatus status) { - String resFile = getResFileProjPath(); - if (resFile == null || resFile.length() == 0) { - status.setError("A resource file name is required."); - } else if (!RES_XML_FILE_REGEX.matcher(resFile).matches()) { - status.setError("The XML file name is not valid."); - } - - if (status.success()) { - sLastResFilePath.put(mProject.getFullPath().toPortableString(), resFile); - - String text = mStringIdField.getText().trim(); - - if (mHelper.isResIdDuplicate(mProject, resFile, text)) { - status.setMessage( - String.format("There's already a string item called '%1$s' in %2$s.", - text, resFile), WizardPage.WARNING); - } else if (mProject.findMember(resFile) == null) { - status.setMessage( - String.format("File %2$s does not exist and will be created.", - text, resFile), WizardPage.INFORMATION); - } - } - - return status; - } - - public String getResFileProjPath() { - return mResFileCombo.getText().trim(); - } - - public class OnConfigSelectorUpdated implements Runnable, ModifyListener { - - /** Regex pattern to parse a valid res path: it reads (/res/folder-name/)+(filename). */ - private final Pattern mPathRegex = Pattern.compile( - "(/res/[a-z][a-zA-Z0-9_-]+/)(.+)"); //$NON-NLS-1$ - - /** Temporary config object used to retrieve the Config Selector value. */ - private FolderConfiguration mTempConfig = new FolderConfiguration(); - - private HashMap> mFolderCache = - new HashMap>(); - private String mLastFolderUsedInCombo = null; - private boolean mInternalConfigChange; - private boolean mInternalFileComboChange; - - /** - * Callback invoked when the {@link ConfigurationSelector} has been changed. - *

    - * The callback does the following: - *

      - *
    • Examine the current file name to retrieve the XML filename, if any. - *
    • Recompute the path based on the configuration selector (e.g. /res/values-fr/). - *
    • Examine the path to retrieve all the files in it. Keep those in a local cache. - *
    • If the XML filename from step 1 is not in the file list, it's a custom file name. - * Insert it and sort it. - *
    • Re-populate the file combo with all the choices. - *
    • Select the original XML file. - */ - public void run() { - if (mInternalConfigChange) { - return; - } - - // get current leafname, if any - String leafName = ""; //$NON-NLS-1$ - String currPath = mResFileCombo.getText(); - Matcher m = mPathRegex.matcher(currPath); - if (m.matches()) { - // Note: groups 1 and 2 cannot be null. - leafName = m.group(2); - currPath = m.group(1); - } else { - // There was a path but it was invalid. Ignore it. - currPath = ""; //$NON-NLS-1$ - } - - // recreate the res path from the current configuration - mConfigSelector.getConfiguration(mTempConfig); - StringBuffer sb = new StringBuffer(RES_FOLDER_ABS); - sb.append(mTempConfig.getFolderName(ResourceFolderType.VALUES)); - sb.append('/'); - - String newPath = sb.toString(); - if (newPath.equals(currPath) && newPath.equals(mLastFolderUsedInCombo)) { - // Path has not changed. No need to reload. - return; - } - - // Get all the files at the new path - - TreeSet filePaths = mFolderCache.get(newPath); - - if (filePaths == null) { - filePaths = new TreeSet(); - - IFolder folder = mProject.getFolder(newPath); - if (folder != null && folder.exists()) { - try { - for (IResource res : folder.members()) { - String name = res.getName(); - if (res.getType() == IResource.FILE && name.endsWith(".xml")) { //$NON-NLS-1$ - filePaths.add(newPath + name); - } - } - } catch (CoreException e) { - // Ignore. - } - } - - mFolderCache.put(newPath, filePaths); - } - - currPath = newPath + leafName; - if (leafName.length() > 0 && !filePaths.contains(currPath)) { - filePaths.add(currPath); - } - - // Fill the combo - try { - mInternalFileComboChange = true; - - mResFileCombo.removeAll(); - - for (String filePath : filePaths) { - mResFileCombo.add(filePath); - } - - int index = -1; - if (leafName.length() > 0) { - index = mResFileCombo.indexOf(currPath); - if (index >= 0) { - mResFileCombo.select(index); - } - } - - if (index == -1) { - mResFileCombo.setText(currPath); - } - - mLastFolderUsedInCombo = newPath; - - } finally { - mInternalFileComboChange = false; - } - - // finally validate the whole page - validatePage(); - } - - /** - * Callback invoked when {@link NewStringBaseImpl#mResFileCombo} has been - * modified. - */ - public void modifyText(ModifyEvent e) { - if (mInternalFileComboChange) { - return; - } - - String wsFolderPath = mResFileCombo.getText(); - - // This is a custom path, we need to sanitize it. - // First it should start with "/res/". Then we need to make sure there are no - // relative paths, things like "../" or "./" or even "//". - wsFolderPath = wsFolderPath.replaceAll("/+\\.\\./+|/+\\./+|//+|\\\\+|^/+", "/"); //$NON-NLS-1$ //$NON-NLS-2$ - wsFolderPath = wsFolderPath.replaceAll("^\\.\\./+|^\\./+", ""); //$NON-NLS-1$ //$NON-NLS-2$ - wsFolderPath = wsFolderPath.replaceAll("/+\\.\\.$|/+\\.$|/+$", ""); //$NON-NLS-1$ //$NON-NLS-2$ - - // We get "res/foo" from selections relative to the project when we want a "/res/foo" path. - if (wsFolderPath.startsWith(RES_FOLDER_REL)) { - wsFolderPath = RES_FOLDER_ABS + wsFolderPath.substring(RES_FOLDER_REL.length()); - - mInternalFileComboChange = true; - mResFileCombo.setText(wsFolderPath); - mInternalFileComboChange = false; - } - - if (wsFolderPath.startsWith(RES_FOLDER_ABS)) { - wsFolderPath = wsFolderPath.substring(RES_FOLDER_ABS.length()); - - int pos = wsFolderPath.indexOf(AndroidConstants.WS_SEP_CHAR); - if (pos >= 0) { - wsFolderPath = wsFolderPath.substring(0, pos); - } - - String[] folderSegments = wsFolderPath.split(FolderConfiguration.QUALIFIER_SEP); - - if (folderSegments.length > 0) { - String folderName = folderSegments[0]; - - if (folderName != null && !folderName.equals(wsFolderPath)) { - // update config selector - mInternalConfigChange = true; - mConfigSelector.setConfiguration(folderSegments); - mInternalConfigChange = false; - } - } - } - - validatePage(); - } - } -} diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringWizard.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringWizard.java deleted file mode 100644 index f7d8fe86..00000000 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringWizard.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.wizards.newstring; - -import org.eclipse.core.resources.IProject; -import org.eclipse.jface.wizard.Wizard; - -/** - * - */ -public class NewStringWizard extends Wizard { - - protected static final String MAIN_PAGE_NAME = "newXmlStringPage"; //$NON-NLS-1$ - - private NewStringWizardPage mMainPage; - - public NewStringWizard(IProject project) { - super(); - - mMainPage = createMainPage(project); - } - - /** - * Creates the wizard page. - *

      - * Please do NOT override this method. - *

      - * This is protected so that it can be overridden by unit tests. - * However the contract of this class is private and NO ATTEMPT will be made - * to maintain compatibility between different versions of the plugin. - * @param project - */ - protected NewStringWizardPage createMainPage(IProject project) { - return new NewStringWizardPage(project, MAIN_PAGE_NAME); - } - - @Override - public void addPages() { - addPage(mMainPage); - super.addPages(); - } - - /** - * @see org.eclipse.jface.wizard.Wizard#performFinish() - */ - @Override - public boolean performFinish() { - // pass - return false; - } - -} diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringWizardPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringWizardPage.java deleted file mode 100644 index 1e2d2727..00000000 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/wizards/newstring/NewStringWizardPage.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Eclipse Public License, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.eclipse.org/org/documents/epl-v10.php - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.ide.eclipse.adt.wizards.newstring; - -import com.android.ide.eclipse.adt.wizards.newstring.NewStringBaseImpl.INewStringPageCallback; -import com.android.ide.eclipse.adt.wizards.newstring.NewStringBaseImpl.ValidationStatus; - -import org.eclipse.core.resources.IProject; -import org.eclipse.jface.wizard.WizardPage; -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.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Text; - -/** - * - */ -class NewStringWizardPage extends WizardPage implements INewStringPageCallback { - - private NewStringBaseImpl mImpl; - - /** Field displaying the user-selected string to be replaced. */ - private Label mStringValueField; - - private String mNewStringId; - - public NewStringWizardPage(IProject project, String pageName) { - super(pageName); - mImpl = new NewStringBaseImpl(project, this); - } - - public String getNewStringValue() { - return mStringValueField.getText(); - } - - public String getNewStringId() { - return mNewStringId; - } - - public String getResFilePathProjPath() { - return mImpl.getResFileProjPath(); - } - - /** - * Create the UI for the new string wizard. - */ - public void createControl(Composite parent) { - Composite content = new Composite(parent, SWT.NONE); - GridLayout layout = new GridLayout(); - layout.numColumns = 1; - content.setLayout(layout); - - mImpl.createControl(content); - setControl(content); - } - - /** - * Creates the top group with the field to replace which string and by what - * and by which options. - * - * @param content A composite with a 1-column grid layout - * @return The {@link Text} field for the new String ID name. - */ - public Text createStringGroup(Composite content) { - - Group group = new Group(content, SWT.NONE); - group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - group.setText("New String"); - - GridLayout layout = new GridLayout(); - layout.numColumns = 2; - group.setLayout(layout); - - Label label = new Label(group, SWT.NONE); - label.setText("String:"); - - mStringValueField = new Label(group, SWT.NONE); - mStringValueField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mStringValueField.setText(""); //$NON-NLS-1$ - - // TODO provide an option to refactor all known occurences of this string. - - // line : Textfield for new ID - - label = new Label(group, SWT.NONE); - label.setText("Replace by R.string."); - - final Text stringIdField = new Text(group, SWT.SINGLE | SWT.LEFT | SWT.BORDER); - stringIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - stringIdField.setText(""); - - mNewStringId = stringIdField.getText().trim(); - - stringIdField.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - if (mImpl.validatePage()) { - mNewStringId = stringIdField.getText().trim(); - } - } - }); - - return stringIdField; - } - - public void postValidatePage(ValidationStatus status) { - // pass - } -} -- 2.11.0