blob: ce828cf2ac203086df50b5acb7b536c1ca98009f [file] [log] [blame]
/*
* 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;
}
}