aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java242
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesEditorDelegate.java144
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesTreePage.java108
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/descriptors/ColorValueDescriptor.java41
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/descriptors/ItemElementDescriptor.java55
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/descriptors/ValuesDescriptors.java337
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/uimodel/UiColorValueNode.java82
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/uimodel/UiItemElementNode.java58
8 files changed, 1067 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java
new file mode 100644
index 000000000..d0ee92ca1
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java
@@ -0,0 +1,242 @@
+/*
+ * 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.editors.values;
+
+import static com.android.SdkConstants.ANDROID_NS_NAME_PREFIX;
+import static com.android.SdkConstants.ANDROID_PREFIX;
+import static com.android.SdkConstants.ATTR_NAME;
+import static com.android.SdkConstants.ATTR_TYPE;
+import static com.android.SdkConstants.PREFIX_RESOURCE_REF;
+import static com.android.SdkConstants.TAG_ITEM;
+import static com.android.SdkConstants.TAG_STYLE;
+import static com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor.ATTRIBUTE_ICON_FILENAME;
+import static com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.DESCRIPTOR_LAYOUT;
+
+import com.android.annotations.VisibleForTesting;
+import com.android.ide.eclipse.adt.internal.editors.AndroidContentAssist;
+import com.android.ide.eclipse.adt.internal.editors.IconFactory;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.DocumentDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.SeparatorAttributeDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiAttributeNode;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiResourceAttributeNode;
+import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
+
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Content Assist Processor for /res/values and /res/drawable XML files
+ * <p>
+ * Further enhancements:
+ * <ul>
+ * <li> Complete prefixes in the style element itself for the name attribute
+ * <li> Complete parent names
+ * </ul>
+ */
+@VisibleForTesting
+public class ValuesContentAssist extends AndroidContentAssist {
+
+ /**
+ * Constructor for ResourcesContentAssist
+ */
+ public ValuesContentAssist() {
+ super(AndroidTargetData.DESCRIPTOR_RESOURCES);
+ }
+
+ @Override
+ protected boolean computeAttributeValues(List<ICompletionProposal> proposals, int offset,
+ String parentTagName, String attributeName, Node node, String wordPrefix,
+ boolean skipEndTag, int replaceLength) {
+ super.computeAttributeValues(proposals, offset, parentTagName, attributeName, node,
+ wordPrefix, skipEndTag, replaceLength);
+
+ if (parentTagName.equals(TAG_ITEM) && ATTR_NAME.equals(attributeName)) {
+
+ // Special case: the user is code completing inside
+ // <style><item name="^"/></style>
+ // In this case, ALL attributes are valid so we need to synthesize
+ // a choice list from all the layout descriptors
+
+ // Add in android: as a completion item?
+ if (startsWith(ANDROID_NS_NAME_PREFIX, wordPrefix)) {
+ proposals.add(new CompletionProposal(ANDROID_NS_NAME_PREFIX,
+ offset - wordPrefix.length(), // replacementOffset
+ wordPrefix.length() + replaceLength, // replacementLength
+ ANDROID_NS_NAME_PREFIX.length(), // cursorPosition
+ IconFactory.getInstance().getIcon(ATTRIBUTE_ICON_FILENAME),
+ null, null, null));
+ }
+
+
+ String attributePrefix = wordPrefix;
+ if (startsWith(attributePrefix, ANDROID_NS_NAME_PREFIX)) {
+ attributePrefix = attributePrefix.substring(ANDROID_NS_NAME_PREFIX.length());
+ }
+
+ AndroidTargetData data = mEditor.getTargetData();
+ if (data != null) {
+ IDescriptorProvider descriptorProvider =
+ data.getDescriptorProvider(
+ AndroidTargetData.DESCRIPTOR_LAYOUT);
+ if (descriptorProvider != null) {
+ ElementDescriptor[] rootElementDescriptors =
+ descriptorProvider.getRootElementDescriptors();
+ Map<String, AttributeDescriptor> matches =
+ new HashMap<String, AttributeDescriptor>(180);
+ for (ElementDescriptor elementDesc : rootElementDescriptors) {
+ for (AttributeDescriptor desc : elementDesc.getAttributes()) {
+ if (desc instanceof SeparatorAttributeDescriptor) {
+ continue;
+ }
+ String name = desc.getXmlLocalName();
+ if (startsWith(name, attributePrefix)) {
+ matches.put(name, desc);
+ }
+ }
+ }
+
+ List<AttributeDescriptor> sorted =
+ new ArrayList<AttributeDescriptor>(matches.size());
+ sorted.addAll(matches.values());
+ Collections.sort(sorted);
+ char needTag = 0;
+ addMatchingProposals(proposals, sorted.toArray(), offset, node, wordPrefix,
+ needTag, true /* isAttribute */, false /* isNew */,
+ skipEndTag /* skipEndTag */, replaceLength);
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ protected void computeTextValues(List<ICompletionProposal> proposals, int offset,
+ Node parentNode, Node currentNode, UiElementNode uiParent,
+ String prefix) {
+ super.computeTextValues(proposals, offset, parentNode, currentNode, uiParent,
+ prefix);
+
+ if (parentNode.getNodeName().equals(TAG_ITEM) &&
+ parentNode.getParentNode() != null &&
+ TAG_STYLE.equals(parentNode.getParentNode().getNodeName())) {
+
+ // Special case: the user is code completing inside
+ // <style><item name="android:foo"/>|</style>
+ // In this case, we need to find the right AttributeDescriptor
+ // for the given attribute and offer its values
+
+ AndroidTargetData data = mEditor.getTargetData();
+ if (data != null) {
+ IDescriptorProvider descriptorProvider =
+ data.getDescriptorProvider(DESCRIPTOR_LAYOUT);
+ if (descriptorProvider != null) {
+
+ Element element = (Element) parentNode;
+ String attrName = element.getAttribute(ATTR_NAME);
+ int pos = attrName.indexOf(':');
+ if (pos >= 0) {
+ attrName = attrName.substring(pos + 1);
+ }
+
+ // Search for an attribute match
+ ElementDescriptor[] rootElementDescriptors =
+ descriptorProvider.getRootElementDescriptors();
+ for (ElementDescriptor elementDesc : rootElementDescriptors) {
+ for (AttributeDescriptor desc : elementDesc.getAttributes()) {
+ if (desc.getXmlLocalName().equals(attrName)) {
+ // Make a ui parent node such that we can attach our
+ // newfound attribute node to something (the code we delegate
+ // to for looking up attribute completions will look at the
+ // parent node and ask for its editor etc.)
+ if (uiParent == null) {
+ DocumentDescriptor documentDescriptor =
+ data.getLayoutDescriptors().getDescriptor();
+ uiParent = documentDescriptor.createUiNode();
+ uiParent.setEditor(mEditor);
+ }
+
+ UiAttributeNode currAttrNode = desc.createUiNode(uiParent);
+ AttribInfo attrInfo = new AttribInfo();
+ Object[] values = getAttributeValueChoices(currAttrNode, attrInfo,
+ prefix);
+ char needTag = attrInfo.needTag;
+ if (attrInfo.correctedPrefix != null) {
+ prefix = attrInfo.correctedPrefix;
+ }
+ boolean isAttribute = true;
+ boolean isNew = false;
+ int replaceLength = computeTextReplaceLength(currentNode, offset);
+ addMatchingProposals(proposals, values, offset, currentNode,
+ prefix, needTag, isAttribute, isNew,
+ false /* skipEndTag */, replaceLength);
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (parentNode.getNodeName().equals(TAG_ITEM)) {
+ // Completing text content inside an <item> tag: offer @resource completion.
+ if (prefix.startsWith(PREFIX_RESOURCE_REF) || prefix.trim().length() == 0) {
+ String[] choices = UiResourceAttributeNode.computeResourceStringMatches(
+ mEditor, null /*attributeDescriptor*/, prefix);
+ if (choices == null || choices.length == 0) {
+ return;
+ }
+
+ // If the parent item tag specifies a type, filter the results
+ Node typeNode = parentNode.getAttributes().getNamedItem(ATTR_TYPE);
+ if (typeNode != null) {
+ String value = typeNode.getNodeValue();
+ List<String> filtered = new ArrayList<String>();
+ for (String s : choices) {
+ if (s.startsWith(ANDROID_PREFIX) ||
+ s.startsWith(PREFIX_RESOURCE_REF+ value)) {
+ filtered.add(s);
+ }
+ }
+ if (filtered.size() > 0) {
+ choices = filtered.toArray(new String[filtered.size()]);
+ }
+ }
+
+ int replaceLength = computeTextReplaceLength(currentNode, offset);
+ addMatchingProposals(proposals, choices, offset, currentNode,
+ prefix, (char) 0 /*needTag*/, true /* isAttribute */, false /*isNew*/,
+ false /* skipEndTag*/,
+ replaceLength);
+
+ }
+ }
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesEditorDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesEditorDelegate.java
new file mode 100644
index 000000000..10f105f85
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesEditorDelegate.java
@@ -0,0 +1,144 @@
+/*
+ * 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.editors.values;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.ide.eclipse.adt.AdtConstants;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlDelegate;
+import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.values.descriptors.ValuesDescriptors;
+import com.android.resources.ResourceFolderType;
+import com.android.xml.AndroidXPathFactory;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.ui.PartInitException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+
+/**
+ * Multi-page form editor for /res/values XML files.
+ */
+public class ValuesEditorDelegate extends CommonXmlDelegate {
+
+ public static class Creator implements IDelegateCreator {
+ @Override
+ @SuppressWarnings("unchecked")
+ public ValuesEditorDelegate createForFile(
+ @NonNull CommonXmlEditor delegator,
+ @Nullable ResourceFolderType type) {
+ if (ResourceFolderType.VALUES == type) {
+ return new ValuesEditorDelegate(delegator);
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Old standalone-editor ID.
+ * Use {@link CommonXmlEditor#ID} instead.
+ */
+ public static final String LEGACY_EDITOR_ID =
+ AdtConstants.EDITORS_NAMESPACE + ".resources.ResourcesEditor"; //$NON-NLS-1$
+
+
+ /**
+ * Creates the form editor for resources XML files.
+ */
+ private ValuesEditorDelegate(CommonXmlEditor editor) {
+ super(editor, new ValuesContentAssist());
+ editor.addDefaultTargetListener();
+ }
+
+ // ---- Base Class Overrides ----
+
+ /**
+ * Create the various form pages.
+ */
+ @Override
+ public void delegateCreateFormPages() {
+ try {
+ getEditor().addPage(new ValuesTreePage(getEditor()));
+ } catch (PartInitException e) {
+ AdtPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$
+ AdtPlugin.getDefault().getLog().log(e.getStatus());
+ }
+ }
+
+ /**
+ * Processes the new XML Model, which XML root node is given.
+ *
+ * @param xml_doc The XML document, if available, or null if none exists.
+ */
+ @Override
+ public void delegateXmlModelChanged(Document xml_doc) {
+ // init the ui root on demand
+ delegateInitUiRootNode(false /*force*/);
+
+ getUiRootNode().setXmlDocument(xml_doc);
+ if (xml_doc != null) {
+ ElementDescriptor resources_desc =
+ ValuesDescriptors.getInstance().getElementDescriptor();
+ try {
+ XPath xpath = AndroidXPathFactory.newXPath();
+ Node node = (Node) xpath.evaluate("/" + resources_desc.getXmlName(), //$NON-NLS-1$
+ xml_doc,
+ XPathConstants.NODE);
+ // Node can be null _or_ it must be the element we searched for.
+ assert node == null || node.getNodeName().equals(resources_desc.getXmlName());
+
+ // Refresh the manifest UI node and all its descendants
+ getUiRootNode().loadFromXmlNode(node);
+ } catch (XPathExpressionException e) {
+ AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
+ resources_desc.getXmlName());
+ }
+ }
+ }
+
+ /**
+ * Creates the initial UI Root Node, including the known mandatory elements.
+ * @param force if true, a new UiRootNode is recreated even if it already exists.
+ */
+ @Override
+ public void delegateInitUiRootNode(boolean force) {
+ // The manifest UI node is always created, even if there's no corresponding XML node.
+ if (getUiRootNode() == null || force) {
+ ElementDescriptor resources_desc =
+ ValuesDescriptors.getInstance().getElementDescriptor();
+ setUiRootNode(resources_desc.createUiNode());
+ getUiRootNode().setEditor(getEditor());
+
+ onDescriptorsChanged();
+ }
+ }
+
+ // ---- Local methods ----
+
+ private void onDescriptorsChanged() {
+ // nothing to be done, as the descriptor are static for now.
+ // FIXME Update when the descriptors are not static
+ }
+}
+
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesTreePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesTreePage.java
new file mode 100644
index 000000000..224eb7301
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesTreePage.java
@@ -0,0 +1,108 @@
+/*
+ * 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.editors.values;
+
+import com.android.ide.common.resources.ResourceFolder;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.editors.IPageImageProvider;
+import com.android.ide.eclipse.adt.internal.editors.IconFactory;
+import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor;
+import com.android.ide.eclipse.adt.internal.editors.layout.configuration.FlagManager;
+import com.android.ide.eclipse.adt.internal.editors.ui.tree.UiTreeBlock;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.forms.IManagedForm;
+import org.eclipse.ui.forms.editor.FormPage;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+import org.eclipse.ui.part.FileEditorInput;
+
+/**
+ * Page for instrumentation settings, part of the AndroidManifest form editor.
+ */
+public final class ValuesTreePage extends FormPage implements IPageImageProvider {
+ /** Page id used for switching tabs programmatically */
+ public final static String PAGE_ID = "res_tree_page"; //$NON-NLS-1$
+
+ /** Container editor */
+ CommonXmlEditor mEditor;
+
+ public ValuesTreePage(CommonXmlEditor editor) {
+ super(editor, PAGE_ID, "Resources"); // tab's label, keep it short
+ mEditor = editor;
+ }
+
+ @Override
+ public Image getPageImage() {
+ // See if we should use a flag icon if this is a language-specific configuration
+ IFile file = mEditor.getInputFile();
+ if (file != null) {
+ IContainer parent = file.getParent();
+ if (parent != null) {
+ Image flag = FlagManager.get().getFlagForFolderName(parent.getName());
+ if (flag != null) {
+ return flag;
+ }
+ }
+ }
+
+ return IconFactory.getInstance().getIcon("editor_page_design"); //$NON-NLS-1$
+ }
+
+ /**
+ * Creates the content in the form hosted in this page.
+ *
+ * @param managedForm the form hosted in this page.
+ */
+ @Override
+ protected void createFormContent(IManagedForm managedForm) {
+ super.createFormContent(managedForm);
+ ScrolledForm form = managedForm.getForm();
+
+ String configText = null;
+ IEditorInput input = mEditor.getEditorInput();
+ if (input instanceof FileEditorInput) {
+ FileEditorInput fileInput = (FileEditorInput)input;
+ IFile iFile = fileInput.getFile();
+
+ ResourceFolder resFolder = ResourceManager.getInstance().getResourceFolder(iFile);
+ if (resFolder != null) {
+ configText = resFolder.getConfiguration().toDisplayString();
+ }
+ }
+
+ if (configText != null) {
+ form.setText(String.format("Android Resources (%1$s)", configText));
+ } else {
+ form.setText("Android Resources");
+ }
+
+ form.setImage(AdtPlugin.getAndroidLogo());
+
+ UiElementNode resources = mEditor.getUiRootNode();
+ UiTreeBlock block = new UiTreeBlock(mEditor, resources,
+ true /* autoCreateRoot */,
+ null /* no element filters */,
+ "Resources Elements",
+ "List of all resources elements in this XML file.");
+ block.createContent(managedForm);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/descriptors/ColorValueDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/descriptors/ColorValueDescriptor.java
new file mode 100644
index 000000000..012785020
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/descriptors/ColorValueDescriptor.java
@@ -0,0 +1,41 @@
+/*
+ * 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.editors.values.descriptors;
+
+import com.android.ide.eclipse.adt.internal.editors.descriptors.TextValueDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiAttributeNode;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiResourceAttributeNode;
+import com.android.ide.eclipse.adt.internal.editors.values.uimodel.UiColorValueNode;
+
+/**
+ * Describes a Color XML element value displayed by an {@link UiColorValueNode}.
+ */
+public final class ColorValueDescriptor extends TextValueDescriptor {
+
+ public ColorValueDescriptor(String uiName, String tooltip) {
+ super(uiName, tooltip);
+ }
+
+ /**
+ * @return A new {@link UiResourceAttributeNode} linked to this theme descriptor.
+ */
+ @Override
+ public UiAttributeNode createUiNode(UiElementNode uiParent) {
+ return new UiColorValueNode(this, uiParent);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/descriptors/ItemElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/descriptors/ItemElementDescriptor.java
new file mode 100644
index 000000000..58ed36e45
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/descriptors/ItemElementDescriptor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008 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.editors.values.descriptors;
+
+import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
+import com.android.ide.eclipse.adt.internal.editors.values.uimodel.UiItemElementNode;
+
+/**
+ * {@link ItemElementDescriptor} is a special version of {@link ElementDescriptor} that
+ * uses a specialized {@link UiItemElementNode} for display.
+ */
+public class ItemElementDescriptor extends ElementDescriptor {
+
+ /**
+ * Constructs a new {@link ItemElementDescriptor} based on its XML name, UI name,
+ * tooltip, SDK url, attributes list, children list and mandatory.
+ *
+ * @param xml_name The XML element node name. Case sensitive.
+ * @param ui_name The XML element name for the user interface, typically capitalized.
+ * @param tooltip An optional tooltip. Can be null or empty.
+ * @param sdk_url An optional SKD URL. Can be null or empty.
+ * @param attributes The list of allowed attributes. Can be null or empty.
+ * @param children The list of allowed children. Can be null or empty.
+ * @param mandatory Whether this node must always exist (even for empty models). A mandatory
+ * UI node is never deleted and it may lack an actual XML node attached. A non-mandatory
+ * UI node MUST have an XML node attached and it will cease to exist when the XML node
+ * ceases to exist.
+ */
+ public ItemElementDescriptor(String xml_name, String ui_name,
+ String tooltip, String sdk_url, AttributeDescriptor[] attributes,
+ ElementDescriptor[] children, boolean mandatory) {
+ super(xml_name, ui_name, tooltip, sdk_url, attributes, children, mandatory);
+ }
+
+ @Override
+ public UiElementNode createUiNode() {
+ return new UiItemElementNode(this);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/descriptors/ValuesDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/descriptors/ValuesDescriptors.java
new file mode 100644
index 000000000..724e01932
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/descriptors/ValuesDescriptors.java
@@ -0,0 +1,337 @@
+/*
+ * 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.editors.values.descriptors;
+
+import static com.android.SdkConstants.ATTR_NAME;
+import static com.android.SdkConstants.ATTR_TYPE;
+import static com.android.SdkConstants.TAG_COLOR;
+import static com.android.SdkConstants.TAG_DIMEN;
+import static com.android.SdkConstants.TAG_DRAWABLE;
+import static com.android.SdkConstants.TAG_INTEGER_ARRAY;
+import static com.android.SdkConstants.TAG_ITEM;
+import static com.android.SdkConstants.TAG_PLURALS;
+import static com.android.SdkConstants.TAG_RESOURCES;
+import static com.android.SdkConstants.TAG_STRING;
+import static com.android.SdkConstants.TAG_STRING_ARRAY;
+import static com.android.SdkConstants.TAG_STYLE;
+
+import com.android.ide.common.api.IAttributeInfo.Format;
+import com.android.ide.common.resources.platform.AttributeInfo;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.EnumAttributeDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.FlagAttributeDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.ListAttributeDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.TextAttributeDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.descriptors.TextValueDescriptor;
+import com.android.resources.ResourceType;
+
+import java.util.EnumSet;
+
+
+/**
+ * Complete description of the structure for resources XML files (under res/values/)
+ */
+public final class ValuesDescriptors implements IDescriptorProvider {
+ private static final ValuesDescriptors sThis = new ValuesDescriptors();
+
+ /** The {@link ElementDescriptor} for the root Resources element. */
+ public final ElementDescriptor mResourcesElement;
+
+ public static ValuesDescriptors getInstance() {
+ return sThis;
+ }
+
+ /*
+ * @see com.android.ide.eclipse.editors.descriptors.IDescriptorProvider#getRootElementDescriptors()
+ */
+ @Override
+ public ElementDescriptor[] getRootElementDescriptors() {
+ return new ElementDescriptor[] { mResourcesElement };
+ }
+
+ @Override
+ public ElementDescriptor getDescriptor() {
+ return mResourcesElement;
+ }
+
+ public ElementDescriptor getElementDescriptor() {
+ return mResourcesElement;
+ }
+
+ private ValuesDescriptors() {
+
+ // Common attributes used in many placed
+
+ // Elements
+
+ AttributeInfo nameAttrInfo = new AttributeInfo(ATTR_NAME, Format.STRING_SET);
+
+ ElementDescriptor color_element = new ElementDescriptor(
+ TAG_COLOR,
+ "Color",
+ "A @color@ value specifies an RGB value with an alpha channel, which can be used in various places such as specifying a solid color for a Drawable or the color to use for text. It always begins with a # character and then is followed by the alpha-red-green-blue information in one of the following formats: #RGB, #ARGB, #RRGGBB or #AARRGGBB.",
+ "http://code.google.com/android/reference/available-resources.html#colorvals", //$NON-NLS-1$
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(ATTR_NAME,
+ null /* nsUri */,
+ nameAttrInfo),
+ new ColorValueDescriptor(
+ "Value*",
+ "A mandatory color value.")
+ .setTooltip("The mandatory name used in referring to this color.")
+ },
+ null, // no child nodes
+ false /* not mandatory */);
+
+ ElementDescriptor string_element = new ElementDescriptor(
+ TAG_STRING,
+ "String",
+ "@Strings@, with optional simple formatting, can be stored and retrieved as resources. You can add formatting to your string by using three standard HTML tags: b, i, and u. If you use an apostrophe or a quote in your string, you must either escape it or enclose the whole string in the other kind of enclosing quotes.",
+ "http://code.google.com/android/reference/available-resources.html#stringresources", //$NON-NLS-1$
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(ATTR_NAME,
+ null /* nsUri */,
+ nameAttrInfo)
+ .setTooltip("The mandatory name used in referring to this string."),
+ new TextValueDescriptor(
+ "Value*",
+ "A mandatory string value.")
+ },
+ null, // no child nodes
+ false /* not mandatory */);
+
+ ElementDescriptor item_element = new ItemElementDescriptor(
+ TAG_ITEM,
+ "Item",
+ null, // TODO find javadoc
+ null, // TODO find link to javadoc
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(ATTR_NAME,
+ null /* nsUri */,
+ nameAttrInfo)
+ .setTooltip("The mandatory name used in referring to this resource."),
+ new ListAttributeDescriptor(ATTR_TYPE,
+ null /* nsUri */,
+ new AttributeInfo(ATTR_TYPE,
+ EnumSet.of(Format.STRING, Format.ENUM)
+ ).setEnumValues(ResourceType.getNames())
+ ).setTooltip("The mandatory type of this resource."),
+ new FlagAttributeDescriptor("format", //$NON-NLS-1$
+ null /* nsUri */,
+ new AttributeInfo("format",
+ EnumSet.of(Format.STRING, Format.FLAG)
+ ).setFlagValues(
+ new String[] {
+ "boolean", //$NON-NLS-1$
+ TAG_COLOR,
+ "dimension", //$NON-NLS-1$
+ "float", //$NON-NLS-1$
+ "fraction", //$NON-NLS-1$
+ "integer", //$NON-NLS-1$
+ "reference", //$NON-NLS-1$
+ "string" //$NON-NLS-1$
+ } )
+ ).setTooltip("The optional format of this resource."),
+ new TextValueDescriptor(
+ "Value",
+ "A standard string, hex color value, or reference to any other resource type.")
+ },
+ null, // no child nodes
+ false /* not mandatory */);
+
+ ElementDescriptor drawable_element = new ElementDescriptor(
+ TAG_DRAWABLE,
+ "Drawable",
+ "A @drawable@ defines a rectangle of color. Android accepts color values written in various web-style formats -- a hexadecimal constant in any of the following forms: #RGB, #ARGB, #RRGGBB, #AARRGGBB. Zero in the alpha channel means transparent. The default value is opaque.",
+ "http://code.google.com/android/reference/available-resources.html#colordrawableresources", //$NON-NLS-1$
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(ATTR_NAME,
+ null /* nsUri */,
+ nameAttrInfo)
+ .setTooltip("The mandatory name used in referring to this drawable."),
+ new TextValueDescriptor(
+ "Value*",
+ "A mandatory color value in the form #RGB, #ARGB, #RRGGBB or #AARRGGBB.")
+ },
+ null, // no child nodes
+ false /* not mandatory */);
+
+ ElementDescriptor dimen_element = new ElementDescriptor(
+ TAG_DIMEN,
+ "Dimension",
+ "You can create common dimensions to use for various screen elements by defining @dimension@ values in XML. A dimension resource is a number followed by a unit of measurement. Supported units are px (pixels), in (inches), mm (millimeters), pt (points at 72 DPI), dp (density-independent pixels) and sp (scale-independent pixels)",
+ "http://code.google.com/android/reference/available-resources.html#dimension", //$NON-NLS-1$
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(ATTR_NAME,
+ null /* nsUri */,
+ nameAttrInfo)
+ .setTooltip("The mandatory name used in referring to this dimension."),
+ new TextValueDescriptor(
+ "Value*",
+ "A mandatory dimension value is a number followed by a unit of measurement. For example: 10px, 2in, 5sp.")
+ },
+ null, // no child nodes
+ false /* not mandatory */);
+
+ ElementDescriptor style_element = new ElementDescriptor(
+ TAG_STYLE,
+ "Style/Theme",
+ "Both @styles and themes@ are defined in a style block containing one or more string or numerical values (typically color values), or references to other resources (drawables and so on).",
+ "http://code.google.com/android/reference/available-resources.html#stylesandthemes", //$NON-NLS-1$
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(ATTR_NAME,
+ null /* nsUri */,
+ nameAttrInfo)
+ .setTooltip("The mandatory name used in referring to this theme."),
+ new TextAttributeDescriptor("parent", //$NON-NLS-1$
+ null /* nsUri */,
+ new AttributeInfo("parent", //$NON-NLS-1$
+ Format.STRING_SET))
+ .setTooltip("An optional parent theme. All values from the specified theme will be inherited into this theme. Any values with identical names that you specify will override inherited values."),
+ },
+ new ElementDescriptor[] {
+ new ElementDescriptor(
+ TAG_ITEM,
+ "Item",
+ "A value to use in this @theme@. It can be a standard string, a hex color value, or a reference to any other resource type.",
+ "http://code.google.com/android/reference/available-resources.html#stylesandthemes", //$NON-NLS-1$
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(ATTR_NAME,
+ null /* nsUri */,
+ nameAttrInfo)
+ .setTooltip("The mandatory name used in referring to this item."),
+ new TextValueDescriptor(
+ "Value*",
+ "A mandatory standard string, hex color value, or reference to any other resource type.")
+ },
+ null, // no child nodes
+ false /* not mandatory */)
+ },
+ false /* not mandatory */);
+
+ ElementDescriptor string_array_element = new ElementDescriptor(
+ TAG_STRING_ARRAY,
+ "String Array",
+ "An array of strings. Strings are added as underlying item elements to the array.",
+ null, // tooltips
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(ATTR_NAME,
+ null /* nsUri */,
+ nameAttrInfo)
+ .setTooltip("The mandatory name used in referring to this string array."),
+ },
+ new ElementDescriptor[] {
+ new ElementDescriptor(
+ TAG_ITEM,
+ "Item",
+ "A string value to use in this string array.",
+ null, // tooltip
+ new AttributeDescriptor[] {
+ new TextValueDescriptor(
+ "Value*",
+ "A mandatory string.")
+ },
+ null, // no child nodes
+ false /* not mandatory */)
+ },
+ false /* not mandatory */);
+
+ ElementDescriptor plurals_element = new ElementDescriptor(
+ TAG_PLURALS,
+ "Quantity Strings (Plurals)",
+ "A quantity string",
+ null, // tooltips
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(ATTR_NAME,
+ null /* nsUri */,
+ nameAttrInfo)
+ .setTooltip("A name for the pair of strings. This name will be used as the resource ID."),
+ },
+ new ElementDescriptor[] {
+ new ElementDescriptor(
+ TAG_ITEM,
+ "Item",
+ "A plural or singular string",
+ null, // tooltip
+ new AttributeDescriptor[] {
+ new EnumAttributeDescriptor(
+ "quantity", "Quantity", null,
+ "A keyword value indicating when this string should be used",
+ new AttributeInfo("quantity", Format.ENUM_SET)
+ .setEnumValues(new String[] {
+ "zero", //$NON-NLS-1$
+ "one", //$NON-NLS-1$
+ "two", //$NON-NLS-1$
+ "few", //$NON-NLS-1$
+ "many", //$NON-NLS-1$
+ "other" //$NON-NLS-1$
+ }))
+ },
+ null, // no child nodes
+ false /* not mandatory */)
+ },
+ false /* not mandatory */);
+
+ ElementDescriptor integer_array_element = new ElementDescriptor(
+ TAG_INTEGER_ARRAY,
+ "Integer Array",
+ "An array of integers. Integers are added as underlying item elements to the array.",
+ null, // tooltips
+ new AttributeDescriptor[] {
+ new TextAttributeDescriptor(ATTR_NAME,
+ null /* nsUri */,
+ nameAttrInfo)
+ .setTooltip("The mandatory name used in referring to this integer array.")
+ },
+ new ElementDescriptor[] {
+ new ElementDescriptor(
+ TAG_ITEM,
+ "Item",
+ "An integer value to use in this integer array.",
+ null, // tooltip
+ new AttributeDescriptor[] {
+ new TextValueDescriptor(
+ "Value*",
+ "A mandatory integer.")
+ },
+ null, // no child nodes
+ false /* not mandatory */)
+ },
+ false /* not mandatory */);
+
+ mResourcesElement = new ElementDescriptor(
+ TAG_RESOURCES,
+ "Resources",
+ null,
+ "http://code.google.com/android/reference/available-resources.html", //$NON-NLS-1$
+ null, // no attributes
+ new ElementDescriptor[] {
+ string_element,
+ color_element,
+ dimen_element,
+ drawable_element,
+ style_element,
+ item_element,
+ string_array_element,
+ integer_array_element,
+ plurals_element,
+ },
+ true /* mandatory */);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/uimodel/UiColorValueNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/uimodel/UiColorValueNode.java
new file mode 100644
index 000000000..9c84b36f9
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/uimodel/UiColorValueNode.java
@@ -0,0 +1,82 @@
+/*
+ * 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.editors.values.uimodel;
+
+import com.android.ide.eclipse.adt.internal.editors.descriptors.TextValueDescriptor;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiAttributeNode;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiTextValueNode;
+
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.widgets.Text;
+
+import java.util.regex.Pattern;
+
+/**
+ * Displays and edits a color XML element value with a custom validator.
+ * <p/>
+ * See {@link UiAttributeNode} for more information.
+ */
+public class UiColorValueNode extends UiTextValueNode {
+
+ /** Accepted RGBA formats are one of #RGB, #ARGB, #RRGGBB or #AARRGGBB. */
+ private static final Pattern RGBA_REGEXP = Pattern.compile(
+ "#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})"); //$NON-NLS-1$
+
+ public UiColorValueNode(TextValueDescriptor attributeDescriptor, UiElementNode uiParent) {
+ super(attributeDescriptor, uiParent);
+ }
+
+ /* (non-java doc)
+ *
+ * Add a modify listener that will check colors have the proper format,
+ * that is one of #RGB, #ARGB, #RRGGBB or #AARRGGBB.
+ */
+ @Override
+ protected void onAddValidators(final Text text) {
+ ModifyListener listener = new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ String color = text.getText();
+ if (RGBA_REGEXP.matcher(color).matches()) {
+ getManagedForm().getMessageManager().removeMessage(text, text);
+ } else {
+ getManagedForm().getMessageManager().addMessage(text,
+ "Accepted color formats are one of #RGB, #ARGB, #RRGGBB or #AARRGGBB.",
+ null /* data */, IMessageProvider.ERROR, text);
+ }
+ }
+ };
+
+ text.addModifyListener(listener);
+
+ // Make sure the validator removes its message(s) when the widget is disposed
+ text.addDisposeListener(new DisposeListener() {
+ @Override
+ public void widgetDisposed(DisposeEvent e) {
+ getManagedForm().getMessageManager().removeMessage(text, text);
+ }
+ });
+
+ // Finally call the validator once to make sure the initial value is processed
+ listener.modifyText(null);
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/uimodel/UiItemElementNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/uimodel/UiItemElementNode.java
new file mode 100644
index 000000000..88ac3e141
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/uimodel/UiItemElementNode.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2008 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.editors.values.uimodel;
+
+import com.android.SdkConstants;
+import com.android.ide.eclipse.adt.AdtUtils;
+import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
+import com.android.ide.eclipse.adt.internal.editors.values.descriptors.ItemElementDescriptor;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * {@link UiItemElementNode} is a special version of {@link UiElementNode} that
+ * customizes the element display to include the item type attribute if present.
+ */
+public class UiItemElementNode extends UiElementNode {
+
+ /**
+ * Creates a new {@link UiElementNode} described by a given {@link ItemElementDescriptor}.
+ *
+ * @param elementDescriptor The {@link ItemElementDescriptor} for the XML node. Cannot be null.
+ */
+ public UiItemElementNode(ItemElementDescriptor elementDescriptor) {
+ super(elementDescriptor);
+ }
+
+ @Override
+ public String getShortDescription() {
+ Node xmlNode = getXmlNode();
+ if (xmlNode != null && xmlNode instanceof Element && xmlNode.hasAttributes()) {
+
+ Element elem = (Element) xmlNode;
+ String type = elem.getAttribute(SdkConstants.ATTR_TYPE);
+ String name = elem.getAttribute(SdkConstants.ATTR_NAME);
+ if (type != null && name != null && type.length() > 0 && name.length() > 0) {
+ type = AdtUtils.capitalize(type);
+ return String.format("%1$s (%2$s %3$s)", name, type, getDescriptor().getUiName());
+ }
+ }
+
+ return super.getShortDescription();
+ }
+}