FileDocCategorySizeDatePackage
UiResourceAttributeNode.javaAPI DocAndroid 1.5 API11426Wed May 06 22:41:10 BST 2009com.android.ide.eclipse.editors.uimodel

UiResourceAttributeNode

public class UiResourceAttributeNode extends UiTextAttributeNode
Represents an XML attribute for a resource that can be modified using a simple text field or a dialog to choose an existing resource.

It can be configured to represent any kind of resource, by providing the desired {@link ResourceType} in the constructor.

See {@link UiTextAttributeNode} for more information.

Fields Summary
private com.android.ide.eclipse.common.resources.ResourceType
mType
Constructors Summary
public UiResourceAttributeNode(com.android.ide.eclipse.common.resources.ResourceType type, com.android.ide.eclipse.editors.descriptors.AttributeDescriptor attributeDescriptor, UiElementNode uiParent)

        super(attributeDescriptor, uiParent);
        
        mType = type;
    
Methods Summary
public voidcreateUiControl(org.eclipse.swt.widgets.Composite parent, org.eclipse.ui.forms.IManagedForm managedForm)

        setManagedForm(managedForm);
        FormToolkit toolkit = managedForm.getToolkit();
        TextAttributeDescriptor desc = (TextAttributeDescriptor) getDescriptor();

        Label label = toolkit.createLabel(parent, desc.getUiName());
        label.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.MIDDLE));
        SectionHelper.addControlTooltip(label, DescriptorsUtils.formatTooltip(desc.getTooltip()));

        Composite composite = toolkit.createComposite(parent);
        composite.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE));
        GridLayout gl = new GridLayout(2, false);
        gl.marginHeight = gl.marginWidth = 0;
        composite.setLayout(gl);
        // Fixes missing text borders under GTK... also requires adding a 1-pixel margin
        // for the text field below
        toolkit.paintBordersFor(composite);
        
        final Text text = toolkit.createText(composite, getCurrentValue());
        GridData gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalIndent = 1;  // Needed by the fixed composite borders under GTK
        text.setLayoutData(gd);
        Button browseButton = toolkit.createButton(composite, "Browse...", SWT.PUSH);
        
        setTextWidget(text);

        // TODO Add a validator using onAddModifyListener
        
        browseButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                String result = showDialog(parent.getShell(), text.getText().trim());
                if (result != null) {
                    text.setText(result);
                }
            }
        });
    
public java.lang.String[]getPossibleValues(java.lang.String prefix)
Gets all the values one could use to auto-complete a "resource" value in an XML content assist.

Typically the user is editing the value of an attribute in a resource XML, e.g.

 "<Button android:test="@string/my_[caret]_string..." 

"prefix" is the value that the user has typed so far (or more exactly whatever is on the left side of the insertion point). In the example above it would be "@style/my_".

To avoid a huge long list of values, the completion works on two levels:

  • If a resource type as been typed so far (e.g. "@style/"), then limit the values to the possible completions that match this type.
  • If no resource type as been typed so far, then return the various types that could be completed. So if the project has only strings and layouts resources, for example, the returned list will only include "@string/" and "@layout/".
Finally if anywhere in the string we find the special token "android:", we use the current framework system resources rather than the project resources. This works for both "@android:style/foo" and "@style/android:foo" conventions even though the reconstructed name will always be of the former form. Note that "android:" here is a keyword specific to Android resources and should not be mixed with an XML namespace for an XML attribute name.

        IResourceRepository repository = null;
        boolean isSystem = false;

        UiElementNode uiNode = getUiParent();
        AndroidEditor editor = uiNode.getEditor();

        if (prefix == null || prefix.indexOf("android:") < 0) {
            IProject project = editor.getProject();
            if (project != null) {
                // get the resource repository for this project and the system resources.
                repository = ResourceManager.getInstance().getProjectResources(project);
            }
        } else {
            // If there's a prefix with "android:" in it, use the system resources
            //
            // TODO find a way to only list *public* framework resources here.
            AndroidTargetData data = editor.getTargetData();
            repository = data.getSystemResources();
            isSystem = true;
        }

        // Get list of potential resource types, either specific to this project
        // or the generic list.
        ResourceType[] resTypes = (repository != null) ?
                    repository.getAvailableResourceTypes() :
                    ResourceType.values();

        // Get the type name from the prefix, if any. It's any word before the / if there's one
        String typeName = null;
        if (prefix != null) {
            Matcher m = Pattern.compile(".*?([a-z]+)/.*").matcher(prefix);
            if (m.matches()) {
                typeName = m.group(1);
            }
        }

        // Now collect results
        ArrayList<String> results = new ArrayList<String>();

        if (typeName == null) {
            // This prefix does not have a / in it, so the resource string is either empty
            // or does not have the resource type in it. Simply offer the list of potential
            // resource types.

            for (ResourceType resType : resTypes) {
                results.add("@" + resType.getName() + "/");
                if (resType == ResourceType.ID) {
                    // Also offer the + version to create an id from scratch
                    results.add("@+" + resType.getName() + "/");
                }
            }
        } else if (repository != null) {
            // We have a style name and a repository. Find all resources that match this
            // type and recreate suggestions out of them.

            ResourceType resType = ResourceType.getEnum(typeName);
            if (resType != null) {
                StringBuilder sb = new StringBuilder();
                sb.append('@");
                if (prefix.indexOf('+") >= 0) {
                    sb.append('+");
                }
                
                if (isSystem) {
                    sb.append("android:");
                }
                
                sb.append(typeName).append('/");
                String base = sb.toString();

                for (ResourceItem item : repository.getResources(resType)) {
                    results.add(base + item.getName());
                }
            }
        }

        return results.toArray(new String[results.size()]);
    
public java.lang.StringshowDialog(org.eclipse.swt.widgets.Shell shell, java.lang.String currentValue)
Shows a dialog letting the user choose a set of enum, and returns a string containing the result.

        // we need to get the project of the file being edited.
        UiElementNode uiNode = getUiParent();
        AndroidEditor editor = uiNode.getEditor();
        IProject project = editor.getProject();
        if (project != null) {
            // get the resource repository for this project and the system resources.
            IResourceRepository projectRepository =
                ResourceManager.getInstance().getProjectResources(project);
            
            if (mType != null) {
                // get the Target Data to get the system resources
                AndroidTargetData data = editor.getTargetData();
                IResourceRepository systemRepository = data.getSystemResources();

                // open a resource chooser dialog for specified resource type.
                ResourceChooser dlg = new ResourceChooser(project,
                        mType,
                        projectRepository,
                        systemRepository,
                        shell);

                dlg.setCurrentResource(currentValue);

                if (dlg.open() == Window.OK) {
                    return dlg.getCurrentResource();
                }
            } else {
                ReferenceChooserDialog dlg = new ReferenceChooserDialog(
                        project,
                        projectRepository,
                        shell);

                dlg.setCurrentResource(currentValue);

                if (dlg.open() == Window.OK) {
                    return dlg.getCurrentResource();
                }
            }
        }

        return null;