/* * Copyright (C) 2007 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.internal.ui; import static com.android.SdkConstants.ANDROID_PREFIX; import static com.android.SdkConstants.PREFIX_RESOURCE_REF; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.resources.ResourceItem; import com.android.ide.common.resources.ResourceRepository; import com.android.ide.common.resources.ResourceResolver; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtUtils; import com.android.ide.eclipse.adt.internal.assetstudio.OpenCreateAssetSetWizardAction; import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart; import com.android.ide.eclipse.adt.internal.editors.layout.properties.PropertyFactory; import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringRefactoring; import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringWizard; import com.android.ide.eclipse.adt.internal.resources.ResourceHelper; import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator; import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources; import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; import com.android.ide.eclipse.adt.internal.sdk.ProjectState; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.resources.ResourceType; import com.android.utils.Pair; import com.google.common.collect.Maps; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IInputValidator; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.window.Window; import org.eclipse.ltk.ui.refactoring.RefactoringWizard; import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; 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.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.AbstractElementListSelectionDialog; import org.eclipse.ui.dialogs.SelectionStatusDialog; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * A dialog to let the user select a resource based on a resource type. */ public class ResourceChooser extends AbstractElementListSelectionDialog implements ModifyListener { /** The return code from the dialog for the user choosing "Clear" */ public static final int CLEAR_RETURN_CODE = -5; /** The dialog button ID for the user choosing "Clear" */ private static final int CLEAR_BUTTON_ID = CLEAR_RETURN_CODE; private Pattern mProjectResourcePattern; private ResourceType mResourceType; private final List<ResourceRepository> mProjectResources; private final ResourceRepository mFrameworkResources; private Pattern mSystemResourcePattern; private Button mProjectButton; private Button mSystemButton; private Button mNewButton; private String mCurrentResource; private final IProject mProject; private IInputValidator mInputValidator; /** Helper object used to draw previews for drawables and colors. */ private ResourcePreviewHelper mPreviewHelper; /** * Textfield for editing the actual returned value, updated when selection * changes. Only shown if {@link #mShowValueText} is true. */ private Text mEditValueText; /** * Whether the {@link #mEditValueText} textfield should be shown when the dialog is created. */ private boolean mShowValueText; /** * Flag indicating whether it's the first time {@link #handleSelectionChanged()} is called. * This is used to filter out the first selection event, always called by the superclass * when the widget is created, to distinguish between "the dialog was created" and * "the user clicked on a selection result", since only the latter should wipe out the * manual user edit shown in the value text. */ private boolean mFirstSelect = true; /** * Label used to show the resolved value in the resource chooser. Only shown * if the {@link #mResourceResolver} field is set. */ private Label mResolvedLabel; /** Resource resolver used to show actual values for resources selected. (Optional). */ private ResourceResolver mResourceResolver; /** * Creates a Resource Chooser dialog. * @param project Project being worked on * @param type The type of the resource to choose * @param projectResources The repository for the project * @param frameworkResources The Framework resource repository * @param parent the parent shell */ private ResourceChooser( @NonNull IProject project, @NonNull ResourceType type, @NonNull List<ResourceRepository> projectResources, @Nullable ResourceRepository frameworkResources, @NonNull Shell parent) { super(parent, new ResourceLabelProvider()); mProject = project; mResourceType = type; mProjectResources = projectResources; mFrameworkResources = frameworkResources; mProjectResourcePattern = Pattern.compile( PREFIX_RESOURCE_REF + mResourceType.getName() + "/(.+)"); //$NON-NLS-1$ mSystemResourcePattern = Pattern.compile( ANDROID_PREFIX + mResourceType.getName() + "/(.+)"); //$NON-NLS-1$ setTitle("Resource Chooser"); setMessage(String.format("Choose a %1$s resource", mResourceType.getDisplayName().toLowerCase(Locale.US))); } /** * Creates a new {@link ResourceChooser} * * @param editor the associated layout editor * @param type the resource type to choose * @return a new {@link ResourceChooser} */ @NonNull public static ResourceChooser create( @NonNull GraphicalEditorPart editor, @NonNull ResourceType type) { IProject project = editor.getProject(); Shell parent = editor.getCanvasControl().getShell(); AndroidTargetData targetData = editor.getEditorDelegate().getEditor().getTargetData(); ResourceChooser chooser = create(project, type, targetData, parent); // When editing Strings, allow editing the value text directly. When we // get inline editing support (where values entered directly into the // textual widget are translated automatically into a resource) this can // go away. if (type == ResourceType.STRING) { chooser.setResourceResolver(editor.getResourceResolver()); chooser.setShowValueText(true); } else if (type == ResourceType.DIMEN || type == ResourceType.INTEGER) { chooser.setResourceResolver(editor.getResourceResolver()); } chooser.setPreviewHelper(new ResourcePreviewHelper(chooser, editor)); return chooser; } /** * Creates a new {@link ResourceChooser} * * @param project the associated project * @param type the resource type to choose * @param targetData the associated framework target data * @param parent the target shell * @return a new {@link ResourceChooser} */ @NonNull public static ResourceChooser create( @NonNull IProject project, @NonNull ResourceType type, @Nullable AndroidTargetData targetData, @NonNull Shell parent) { ResourceManager manager = ResourceManager.getInstance(); List<ResourceRepository> projectResources = new ArrayList<ResourceRepository>(); ProjectResources resources = manager.getProjectResources(project); projectResources.add(resources); // Add in library project resources ProjectState projectState = Sdk.getProjectState(project); if (projectState != null) { List<IProject> libraries = projectState.getFullLibraryProjects(); if (libraries != null && !libraries.isEmpty()) { for (IProject library : libraries) { projectResources.add(manager.getProjectResources(library)); } } } ResourceRepository frameworkResources = targetData != null ? targetData.getFrameworkResources() : null; return new ResourceChooser(project, type, projectResources, frameworkResources, parent); } /** * Sets whether this dialog should show the value field as a separate text * value (and take the resulting value of the dialog from this text field * rather than from the selection) * * @param showValueText if true, show the value text field * @return this, for constructor chaining */ public ResourceChooser setShowValueText(boolean showValueText) { mShowValueText = showValueText; return this; } /** * Sets the resource resolver to use to show resolved values for the current * selection * * @param resourceResolver the resource resolver to use * @return this, for constructor chaining */ public ResourceChooser setResourceResolver(ResourceResolver resourceResolver) { mResourceResolver = resourceResolver; return this; } /** * Sets the {@link ResourcePreviewHelper} to use to preview drawable * resources, if any * * @param previewHelper the helper to use * @return this, for constructor chaining */ public ResourceChooser setPreviewHelper(ResourcePreviewHelper previewHelper) { mPreviewHelper = previewHelper; return this; } /** * Sets the initial dialog size * * @param width the initial width * @param height the initial height * @return this, for constructor chaining */ public ResourceChooser setInitialSize(int width, int height) { setSize(width, height); return this; } @Override public void create() { super.create(); if (mShowValueText) { mEditValueText.selectAll(); mEditValueText.setFocus(); } } @Override protected void createButtonsForButtonBar(Composite parent) { createButton(parent, CLEAR_BUTTON_ID, "Clear", false /*defaultButton*/); super.createButtonsForButtonBar(parent); } @Override protected void buttonPressed(int buttonId) { super.buttonPressed(buttonId); if (buttonId == CLEAR_BUTTON_ID) { assert CLEAR_RETURN_CODE != Window.OK && CLEAR_RETURN_CODE != Window.CANCEL; setReturnCode(CLEAR_RETURN_CODE); close(); } } /** * Sets the currently selected item * * @param resource the resource url for the currently selected item * @return this, for constructor chaining */ public ResourceChooser setCurrentResource(@Nullable String resource) { mCurrentResource = resource; if (mShowValueText && mEditValueText != null) { mEditValueText.setText(resource); } return this; } /** * Returns the currently selected url * * @return the currently selected url */ @Nullable public String getCurrentResource() { return mCurrentResource; } /** * Sets the input validator to use, if any * * @param inputValidator the validator * @return this, for constructor chaining */ public ResourceChooser setInputValidator(@Nullable IInputValidator inputValidator) { mInputValidator = inputValidator; return this; } @Override protected void computeResult() { if (mShowValueText) { mCurrentResource = mEditValueText.getText(); if (mCurrentResource.length() == 0) { mCurrentResource = null; } return; } computeResultFromSelection(); } private void computeResultFromSelection() { if (getSelectionIndex() == -1) { mCurrentResource = null; return; } Object[] elements = getSelectedElements(); if (elements.length == 1 && elements[0] instanceof ResourceItem) { ResourceItem item = (ResourceItem)elements[0]; mCurrentResource = item.getXmlString(mResourceType, mSystemButton.getSelection()); if (mInputValidator != null && mInputValidator.isValid(mCurrentResource) != null) { mCurrentResource = null; } } } @Override protected Control createDialogArea(Composite parent) { Composite top = (Composite)super.createDialogArea(parent); createMessageArea(top); createButtons(top); createFilterText(top); createFilteredList(top); // create the "New Resource" button createNewResButtons(top); // Optionally create the value text field, if {@link #mShowValueText} is true createValueField(top); setupResourceList(); selectResourceString(mCurrentResource); return top; } /** * Creates the radio button to switch between project and system resources. * @param top the parent composite */ private void createButtons(Composite top) { mProjectButton = new Button(top, SWT.RADIO); mProjectButton.setText("Project Resources"); mProjectButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { super.widgetSelected(e); if (mProjectButton.getSelection()) { // Clear selection before changing the list contents. This works around // a bug in the superclass where switching to the framework resources, // choosing one of the last resources, then switching to the project // resources would cause an exception when calling getSelection() because // selection state doesn't get cleared when we set new contents on // the filtered list. fFilteredList.setSelection(new int[0]); setupResourceList(); updateNewButton(false /*isSystem*/); updateValue(); } } }); mSystemButton = new Button(top, SWT.RADIO); mSystemButton.setText("System Resources"); mSystemButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { super.widgetSelected(e); if (mSystemButton.getSelection()) { fFilteredList.setSelection(new int[0]); setupResourceList(); updateNewButton(true /*isSystem*/); updateValue(); } } }); if (mFrameworkResources == null) { mSystemButton.setVisible(false); } } /** * Creates the "New Resource" button. * @param top the parent composite */ private void createNewResButtons(Composite top) { mNewButton = new Button(top, SWT.NONE); String title = String.format("New %1$s...", mResourceType.getDisplayName()); if (mResourceType == ResourceType.DRAWABLE) { title = "Create New Icon..."; } mNewButton.setText(title); mNewButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { super.widgetSelected(e); if (mResourceType == ResourceType.STRING) { // Special case: Use Extract String refactoring wizard UI String newName = createNewString(); selectAddedItem(newName); } else if (mResourceType == ResourceType.DRAWABLE) { // Special case: Use the "Create Icon Set" wizard OpenCreateAssetSetWizardAction action = new OpenCreateAssetSetWizardAction(mProject); action.run(); List<IResource> files = action.getCreatedFiles(); if (files != null && files.size() > 0) { String newName = AdtUtils.stripAllExtensions(files.get(0).getName()); // Recompute the "current resource" to select the new id ResourceItem[] items = setupResourceList(); selectItemName(newName, items); } } else { if (ResourceHelper.isValueBasedResourceType(mResourceType)) { String newName = createNewValue(mResourceType); if (newName != null) { selectAddedItem(newName); } } else { String newName = createNewFile(mResourceType); if (newName != null) { selectAddedItem(newName); } } } } private void selectAddedItem(@NonNull String newName) { // Recompute the "current resource" to select the new id ResourceItem[] items = setupResourceList(); // Ensure that the name is in the list. There's a delay after // an item is added (until the builder runs and processes the delta) // so if it's not in the list, add it boolean found = false; for (ResourceItem item : items) { if (newName.equals(item.getName())) { found = true; break; } } if (!found) { ResourceItem[] newItems = new ResourceItem[items.length + 1]; System.arraycopy(items, 0, newItems, 0, items.length); newItems[items.length] = new ResourceItem(newName); items = newItems; Arrays.sort(items); setListElements(items); fFilteredList.setEnabled(newItems.length > 0); } selectItemName(newName, items); } }); } /** * Creates the value text field. * * @param top the parent composite */ private void createValueField(Composite top) { if (mShowValueText) { mEditValueText = new Text(top, SWT.BORDER); if (mCurrentResource != null) { mEditValueText.setText(mCurrentResource); } mEditValueText.addModifyListener(this); GridData data = new GridData(); data.grabExcessVerticalSpace = false; data.grabExcessHorizontalSpace = true; data.horizontalAlignment = GridData.FILL; data.verticalAlignment = GridData.BEGINNING; mEditValueText.setLayoutData(data); mEditValueText.setFont(top.getFont()); } if (mResourceResolver != null) { mResolvedLabel = new Label(top, SWT.NONE); GridData data = new GridData(); data.grabExcessVerticalSpace = false; data.grabExcessHorizontalSpace = true; data.horizontalAlignment = GridData.FILL; data.verticalAlignment = GridData.BEGINNING; mResolvedLabel.setLayoutData(data); } Composite workaround = PropertyFactory.addWorkaround(top); if (workaround != null) { workaround.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1)); } } private void updateResolvedLabel() { if (mResourceResolver == null) { return; } String v = null; if (mCurrentResource != null) { v = mCurrentResource; if (mCurrentResource.startsWith(PREFIX_RESOURCE_REF)) { ResourceValue value = mResourceResolver.findResValue(mCurrentResource, false); if (value != null) { v = value.getValue(); } } } if (v == null) { v = ""; } mResolvedLabel.setText(String.format("Resolved Value: %1$s", v)); } @Override protected void handleSelectionChanged() { super.handleSelectionChanged(); if (mInputValidator != null) { Object[] elements = getSelectedElements(); if (elements.length == 1 && elements[0] instanceof ResourceItem) { ResourceItem item = (ResourceItem)elements[0]; String current = item.getXmlString(mResourceType, mSystemButton.getSelection()); String error = mInputValidator.isValid(current); IStatus status; if (error != null) { status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, error); } else { status = new Status(IStatus.OK, AdtPlugin.PLUGIN_ID, null); } updateStatus(status); } } updateValue(); } private void updateValue() { if (mPreviewHelper != null) { computeResult(); mPreviewHelper.updatePreview(mResourceType, mCurrentResource); } if (mShowValueText) { if (mFirstSelect) { mFirstSelect = false; mEditValueText.selectAll(); } else { computeResultFromSelection(); mEditValueText.setText(mCurrentResource != null ? mCurrentResource : ""); } } if (mResourceResolver != null) { if (!mShowValueText) { computeResultFromSelection(); } updateResolvedLabel(); } } @Nullable private String createNewFile(ResourceType type) { // Show a name/value dialog entering the key name and the value Shell shell = AdtPlugin.getShell(); if (shell == null) { return null; } ResourceNameValidator validator = ResourceNameValidator.create(true /*allowXmlExtension*/, mProject, mResourceType); InputDialog d = new InputDialog( AdtPlugin.getShell(), "Enter name", // title "Enter name", "", //$NON-NLS-1$ validator); if (d.open() == Window.OK) { String name = d.getValue().trim(); if (name.length() == 0) { return null; } Pair<IFile, IRegion> resource = ResourceHelper.createResource(mProject, type, name, null); if (resource != null) { return name; } } return null; } @Nullable private String createNewValue(ResourceType type) { // Show a name/value dialog entering the key name and the value Shell shell = AdtPlugin.getShell(); if (shell == null) { return null; } NameValueDialog dialog = new NameValueDialog(shell, getFilter()); if (dialog.open() != Window.OK) { return null; } String name = dialog.getName(); String value = dialog.getValue(); if (name.length() == 0 || value.length() == 0) { return null; } Pair<IFile, IRegion> resource = ResourceHelper.createResource(mProject, type, name, value); if (resource != null) { return name; } return null; } private String createNewString() { ExtractStringRefactoring ref = new ExtractStringRefactoring( mProject, true /*enforceNew*/); RefactoringWizard wizard = new ExtractStringWizard(ref, mProject); RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard); try { IWorkbench w = PlatformUI.getWorkbench(); if (op.run(w.getDisplay().getActiveShell(), wizard.getDefaultPageTitle()) == IDialogConstants.OK_ID) { return ref.getXmlStringId(); } } catch (InterruptedException ex) { // Interrupted. Pass. } return null; } /** * Setups the current list. */ private ResourceItem[] setupResourceList() { Collection<ResourceItem> items = null; if (mProjectButton.getSelection()) { if (mProjectResources.size() == 1) { items = mProjectResources.get(0).getResourceItemsOfType(mResourceType); } else { Map<String, ResourceItem> merged = Maps.newHashMapWithExpectedSize(200); for (ResourceRepository repository : mProjectResources) { for (ResourceItem item : repository.getResourceItemsOfType(mResourceType)) { if (!merged.containsKey(item.getName())) { merged.put(item.getName(), item); } } } items = merged.values(); } } else if (mSystemButton.getSelection()) { items = mFrameworkResources.getResourceItemsOfType(mResourceType); } if (items == null) { items = Collections.emptyList(); } ResourceItem[] arrayItems = items.toArray(new ResourceItem[items.size()]); // sort the array Arrays.sort(arrayItems); setListElements(arrayItems); fFilteredList.setEnabled(arrayItems.length > 0); return arrayItems; } /** * Select an item by its name, if possible. */ private void selectItemName(String itemName, ResourceItem[] items) { if (itemName == null || items == null) { return; } for (ResourceItem item : items) { if (itemName.equals(item.getName())) { setSelection(new Object[] { item }); break; } } } /** * Select an item by its full resource string. * This also selects between project and system repository based on the resource string. */ private void selectResourceString(String resourceString) { boolean isSystem = false; String itemName = null; if (resourceString != null) { // Is this a system resource? // If not a system resource or if they are not available, this will be a project res. Matcher m = mSystemResourcePattern.matcher(resourceString); if (m.matches()) { itemName = m.group(1); isSystem = true; } if (!isSystem && itemName == null) { // Try to match project resource name m = mProjectResourcePattern.matcher(resourceString); if (m.matches()) { itemName = m.group(1); } } } // Update the repository selection mProjectButton.setSelection(!isSystem); mSystemButton.setSelection(isSystem); updateNewButton(isSystem); // Update the list ResourceItem[] items = setupResourceList(); // If we have a selection name, select it if (itemName != null) { selectItemName(itemName, items); } } private void updateNewButton(boolean isSystem) { mNewButton.setEnabled(!isSystem && ResourceHelper.canCreateResourceType(mResourceType)); } // ---- Implements ModifyListener ---- @Override public void modifyText(ModifyEvent e) { if (e.getSource() == mEditValueText && mResourceResolver != null) { mCurrentResource = mEditValueText.getText(); if (mCurrentResource.startsWith(PREFIX_RESOURCE_REF)) { if (mProjectResourcePattern.matcher(mCurrentResource).matches() || mSystemResourcePattern.matcher(mCurrentResource).matches()) { updateResolvedLabel(); } } else { updateResolvedLabel(); } } } /** Dialog asking for a Name/Value pair */ private class NameValueDialog extends SelectionStatusDialog implements Listener { private org.eclipse.swt.widgets.Text mNameText; private org.eclipse.swt.widgets.Text mValueText; private String mInitialName; private String mName; private String mValue; private ResourceNameValidator mValidator; public NameValueDialog(Shell parent, String initialName) { super(parent); mInitialName = initialName; } @Override protected Control createDialogArea(Composite parent) { Composite container = new Composite(parent, SWT.NONE); container.setLayout(new GridLayout(2, false)); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1); // Wide enough to accommodate the error label gridData.widthHint = 500; container.setLayoutData(gridData); Label nameLabel = new Label(container, SWT.NONE); nameLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); nameLabel.setText("Name:"); mNameText = new org.eclipse.swt.widgets.Text(container, SWT.BORDER); mNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); if (mInitialName != null) { mNameText.setText(mInitialName); mNameText.selectAll(); } Label valueLabel = new Label(container, SWT.NONE); valueLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); valueLabel.setText("Value:"); mValueText = new org.eclipse.swt.widgets.Text(container, SWT.BORDER); mValueText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); mNameText.addListener(SWT.Modify, this); mValueText.addListener(SWT.Modify, this); validate(); return container; } @Override protected void computeResult() { mName = mNameText.getText().trim(); mValue = mValueText.getText().trim(); } private String getName() { return mName; } private String getValue() { return mValue; } @Override public void handleEvent(Event event) { validate(); } private void validate() { IStatus status; computeResult(); if (mName.length() == 0) { status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, "Enter a name"); } else if (mValue.length() == 0) { status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, "Enter a value"); } else { if (mValidator == null) { mValidator = ResourceNameValidator.create(false, mProject, mResourceType); } String error = mValidator.isValid(mName); if (error != null) { status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, error); } else { status = new Status(IStatus.OK, AdtPlugin.PLUGIN_ID, null); } } updateStatus(status); } } /** * Open the resource chooser for the given type, associated with the given * editor * * @param graphicalEditor the editor associated with the resource to be * chosen (used to find the associated Android target to be used * for framework resources etc) * @param type the resource type to be chosen * @param currentValue the current value, or null * @param validator a validator to be used, or null * @return the chosen resource, null if cancelled and "" if value should be * cleared */ public static String chooseResource( @NonNull GraphicalEditorPart graphicalEditor, @NonNull ResourceType type, String currentValue, IInputValidator validator) { ResourceChooser chooser = create(graphicalEditor, type). setCurrentResource(currentValue); if (validator != null) { // Ensure wide enough to accommodate validator error message chooser.setSize(85, 10); chooser.setInputValidator(validator); } int result = chooser.open(); if (result == ResourceChooser.CLEAR_RETURN_CODE) { return ""; //$NON-NLS-1$ } else if (result == Window.OK) { return chooser.getCurrentResource(); } return null; } }