diff options
25 files changed, 655 insertions, 190 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/icons/SearchView.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/SearchView.png Binary files differindex c41a2cd..2b45fc2 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/icons/SearchView.png +++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/SearchView.png diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/icons/VerticalLinearLayout.png b/eclipse/plugins/com.android.ide.eclipse.adt/icons/VerticalLinearLayout.png Binary files differnew file mode 100644 index 0000000..e03c16e --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/icons/VerticalLinearLayout.png diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java index 97da864c..a148836 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/LayoutConstants.java @@ -41,6 +41,7 @@ public class LayoutConstants { public static final String TABLE_LAYOUT = "TableLayout"; //$NON-NLS-1$ public static final String TABLE_ROW = "TableRow"; //$NON-NLS-1$ public static final String LIST_VIEW = "ListView"; //$NON-NLS-1$ + public static final String EDIT_TEXT = "EditText"; //$NON-NLS-1$ public static final String GALLERY = "Gallery"; //$NON-NLS-1$ public static final String GRID_VIEW = "GridView"; //$NON-NLS-1$ public static final String SCROLL_VIEW = "ScrollView"; //$NON-NLS-1$ @@ -134,7 +135,9 @@ public class LayoutConstants { public static final String GRAVITY_VALUE_FILL = "fill"; //$NON-NLS-1$ /** The default prefix used for the {@link #ANDROID_URI} name space */ - public static final String ANDROID_NS_PREFIX = "android"; //$NON-NLS-1$ + public static final String ANDROID_NS_NAME = "android"; //$NON-NLS-1$ + /** The default prefix used for the {@link #ANDROID_URI} name space including the colon */ + public static final String ANDROID_NS_NAME_PREFIX = "android:"; //$NON-NLS-1$ /** * Namespace for the Android resource XML, i.e. diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java index 1fea25a..97ed5a6 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/DescriptorsUtils.java @@ -21,6 +21,7 @@ import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_BELOW; import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_HEIGHT; import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_WIDTH; import static com.android.ide.common.layout.LayoutConstants.ATTR_TEXT; +import static com.android.ide.common.layout.LayoutConstants.EDIT_TEXT; import static com.android.ide.common.layout.LayoutConstants.EXPANDABLE_LIST_VIEW; import static com.android.ide.common.layout.LayoutConstants.FQCN_ADAPTER_VIEW; import static com.android.ide.common.layout.LayoutConstants.GALLERY; @@ -677,49 +678,53 @@ public final class DescriptorsUtils { * <p/> * This does not override attributes which are not empty. */ - public static void setDefaultLayoutAttributes(UiElementNode ui_node, boolean updateLayout) { + public static void setDefaultLayoutAttributes(UiElementNode node, boolean updateLayout) { // if this ui_node is a layout and we're adding it to a document, use match_parent for // both W/H. Otherwise default to wrap_layout. - boolean fill = ui_node.getDescriptor().hasChildren() && - ui_node.getUiParent() instanceof UiDocumentNode; - ui_node.setAttributeValue( + ElementDescriptor descriptor = node.getDescriptor(); + boolean fill = descriptor.hasChildren() && + node.getUiParent() instanceof UiDocumentNode; + node.setAttributeValue( ATTR_LAYOUT_WIDTH, SdkConstants.NS_RESOURCES, fill ? VALUE_FILL_PARENT : VALUE_WRAP_CONTENT, false /* override */); - ui_node.setAttributeValue( + node.setAttributeValue( ATTR_LAYOUT_HEIGHT, SdkConstants.NS_RESOURCES, fill ? VALUE_FILL_PARENT : VALUE_WRAP_CONTENT, false /* override */); - String widget_id = getFreeWidgetId(ui_node); - if (widget_id != null) { - ui_node.setAttributeValue( + String freeId = getFreeWidgetId(node); + if (freeId != null) { + node.setAttributeValue( ATTR_ID, SdkConstants.NS_RESOURCES, - widget_id, + freeId, false /* override */); } - String widget_type = ui_node.getDescriptor().getUiName(); - ui_node.setAttributeValue( + // Don't set default text value into edit texts - they typically start out blank + if (!descriptor.getXmlLocalName().equals(EDIT_TEXT)) { + String type = descriptor.getUiName(); + node.setAttributeValue( ATTR_TEXT, SdkConstants.NS_RESOURCES, - widget_type, + type, false /*override*/); + } if (updateLayout) { - UiElementNode ui_parent = ui_node.getUiParent(); - if (ui_parent != null && - ui_parent.getDescriptor().getXmlLocalName().equals( + UiElementNode parent = node.getUiParent(); + if (parent != null && + parent.getDescriptor().getXmlLocalName().equals( RELATIVE_LAYOUT)) { - UiElementNode ui_previous = ui_node.getUiPreviousSibling(); - if (ui_previous != null) { - String id = ui_previous.getAttributeValue(ATTR_ID); + UiElementNode previous = node.getUiPreviousSibling(); + if (previous != null) { + String id = previous.getAttributeValue(ATTR_ID); if (id != null && id.length() > 0) { id = id.replace("@+", "@"); //$NON-NLS-1$ //$NON-NLS-2$ - ui_node.setAttributeValue( + node.setAttributeValue( ATTR_LAYOUT_BELOW, SdkConstants.NS_RESOURCES, id, diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/ElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/ElementDescriptor.java index f4cb251..793ea14 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/ElementDescriptor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/ElementDescriptor.java @@ -16,6 +16,8 @@ package com.android.ide.eclipse.adt.internal.editors.descriptors; +import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME_PREFIX; + import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.editors.IconFactory; import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode; @@ -210,7 +212,7 @@ public class ElementDescriptor implements Comparable<ElementDescriptor> { */ public final String getNamespace() { // For now we hard-code the prefix as being "android" - if (mXmlName.startsWith("android:")) { //$NON-NLs-1$ + if (mXmlName.startsWith(ANDROID_NS_NAME_PREFIX)) { return SdkConstants.NS_RESOURCES; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java index d82774d..3c5cea4 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java @@ -16,6 +16,8 @@ package com.android.ide.eclipse.adt.internal.editors.layout.configuration; +import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME_PREFIX; + import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.rendering.api.StyleResourceValue; import com.android.ide.common.sdk.LoadStatus; @@ -1964,9 +1966,9 @@ public class ConfigurationComposite extends Composite { } // check for framework identifier. - if (parentStyle.startsWith("android:")) { + if (parentStyle.startsWith(ANDROID_NS_NAME_PREFIX)) { frameworkStyle = true; - parentStyle = parentStyle.substring("android:".length()); + parentStyle = parentStyle.substring(ANDROID_NS_NAME_PREFIX.length()); } // at this point we could have the format style/<name>. we want only the name diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java index b1b7754..41b07b5 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/ViewElementDescriptor.java @@ -47,13 +47,13 @@ import org.eclipse.swt.graphics.Image; * * @see ElementDescriptor */ -public final class ViewElementDescriptor extends ElementDescriptor { +public class ViewElementDescriptor extends ElementDescriptor { /** The full class name (FQCN) of this view. */ - private String mFullClassName; + private final String mFullClassName; /** The list of layout attributes. Can be empty but not null. */ - private AttributeDescriptor[] mLayoutAttributes; + private final AttributeDescriptor[] mLayoutAttributes; /** The super-class descriptor. Can be null. */ private ViewElementDescriptor mSuperClassDesc; @@ -100,6 +100,7 @@ public final class ViewElementDescriptor extends ElementDescriptor { public ViewElementDescriptor(String xml_name, String fullClassName) { super(xml_name); mFullClassName = fullClassName; + mLayoutAttributes = null; } /** diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java index 01f153b..d29544d 100755 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java @@ -1283,7 +1283,7 @@ public class LayoutCanvas extends Canvas { // A root node requires the Android XMLNS uiNew.setAttributeValue( - LayoutConstants.ANDROID_NS_PREFIX, + LayoutConstants.ANDROID_NS_NAME, XmlnsAttributeDescriptor.XMLNS_URI, SdkConstants.NS_RESOURCES, true /*override*/); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java index 21dff30..4323075 100755 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java @@ -17,10 +17,13 @@ package com.android.ide.eclipse.adt.internal.editors.layout.gle2; import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI; +import static com.android.ide.common.layout.LayoutConstants.ATTR_ORIENTATION; import static com.android.ide.common.layout.LayoutConstants.ATTR_SRC; import static com.android.ide.common.layout.LayoutConstants.ATTR_TEXT; import static com.android.ide.common.layout.LayoutConstants.DRAWABLE_PREFIX; import static com.android.ide.common.layout.LayoutConstants.LAYOUT_PREFIX; +import static com.android.ide.common.layout.LayoutConstants.LINEAR_LAYOUT; +import static com.android.ide.common.layout.LayoutConstants.VALUE_VERTICAL; import static org.eclipse.jface.viewers.StyledString.QUALIFIER_STYLER; import com.android.annotations.VisibleForTesting; @@ -468,7 +471,20 @@ public class OutlinePage extends ContentOutlinePage UiElementNode node = (UiElementNode) element; ElementDescriptor desc = node.getDescriptor(); if (desc != null) { - Image img = desc.getIcon(); + Image img = null; + // Special case for the common case of vertical linear layouts: + // show vertical linear icon (the default icon shows horizontal orientation) + if (desc.getUiName().equals(LINEAR_LAYOUT)) { + Element e = (Element) node.getXmlNode(); + if (VALUE_VERTICAL.equals(e.getAttributeNS(ANDROID_URI, + ATTR_ORIENTATION))) { + IconFactory factory = IconFactory.getInstance(); + img = factory.getIcon("VerticalLinearLayout"); //$NON-NLS-1$ + } + } + if (img == null) { + img = desc.getIcon(); + } if (img != null) { if (node.hasError()) { return new ErrorImageComposite(img).createImage(); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java index 5c48d49..9e090fd 100755 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PaletteControl.java @@ -40,6 +40,7 @@ import com.android.ide.eclipse.adt.internal.editors.layout.configuration.Configu import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor; import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeFactory; import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy; +import com.android.ide.eclipse.adt.internal.editors.layout.gre.PaletteMetadataDescriptor; import com.android.ide.eclipse.adt.internal.editors.layout.gre.ViewMetadataRepository; import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode; import com.android.ide.eclipse.adt.internal.editors.ui.DecorComposite; @@ -50,7 +51,6 @@ import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.SdkConstants; import com.android.util.Pair; import org.eclipse.jface.action.Action; @@ -437,7 +437,14 @@ public class PaletteControl extends Composite { categoryToItems.put(category, categoryItems); } - if (expandedCategories == null && headers.size() > 0) { + // Set the categories to expand the first item if + // (1) we don't have a previously selected category, or + // (2) there's just one category anyway, or + // (3) the set of categories have changed so our previously selected category + // doesn't exist anymore (can happen when you toggle "Show Categories") + if ((expandedCategories == null && headers.size() > 0) || headers.size() == 1 || + (expandedCategories != null && expandedCategories.size() >= 1 + && !headers.contains(expandedCategories.iterator().next()))) { // Expand the first category if we don't have a previous selection (e.g. refresh) expandedCategories = Collections.singleton(headers.get(0)); } @@ -649,6 +656,10 @@ public class PaletteControl extends Composite { null /* parentFqcn */, bounds /* bounds */, null /* parentBounds */); + if (mDesc instanceof PaletteMetadataDescriptor) { + PaletteMetadataDescriptor pm = (PaletteMetadataDescriptor) mDesc; + pm.initializeNew(se); + } mElements = new SimpleElement[] { se }; // Register this as the current dragged data @@ -784,14 +795,20 @@ public class PaletteControl extends Composite { attr.setValue(ANDROID_URI); element.getAttributes().setNamedItemNS(attr); - element.setAttributeNS(SdkConstants.NS_RESOURCES, + element.setAttributeNS(ANDROID_URI, ATTR_LAYOUT_WIDTH, VALUE_WRAP_CONTENT); - element.setAttributeNS(SdkConstants.NS_RESOURCES, + element.setAttributeNS(ANDROID_URI, ATTR_LAYOUT_HEIGHT, VALUE_WRAP_CONTENT); // This doesn't apply to all, but doesn't seem to cause harm and makes for a // better experience with text-oriented views like buttons and texts - element.setAttributeNS(SdkConstants.NS_RESOURCES, ATTR_TEXT, mDesc.getUiName()); + element.setAttributeNS(ANDROID_URI, ATTR_TEXT, mDesc.getUiName()); + + // Is this a palette variation? + if (mDesc instanceof PaletteMetadataDescriptor) { + PaletteMetadataDescriptor pm = (PaletteMetadataDescriptor) mDesc; + pm.initializeNew(element); + } document.appendChild(element); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PreviewIconFactory.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PreviewIconFactory.java index e8b4fba..f6db7da 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PreviewIconFactory.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PreviewIconFactory.java @@ -33,6 +33,7 @@ import com.android.ide.eclipse.adt.AdtPlugin; 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.layout.LayoutEditor; +import com.android.ide.eclipse.adt.internal.editors.layout.gre.PaletteMetadataDescriptor; import com.android.ide.eclipse.adt.internal.editors.layout.gre.ViewMetadataRepository; import com.android.ide.eclipse.adt.internal.editors.layout.gre.ViewMetadataRepository.RenderMode; import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode; @@ -41,6 +42,7 @@ import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; import com.android.util.Pair; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.graphics.RGB; import org.w3c.dom.Attr; @@ -236,7 +238,7 @@ public class PreviewIconFactory { // Important to get these sizes large enough for clients that don't support // RenderMode.FULL_EXPAND such as 1.6 int width = 200; - int height = 2000; + int height = documentElement.getChildNodes().getLength() == 1 ? 400 : 1600; Set<UiElementNode> expandNodes = Collections.<UiElementNode>emptySet(); RenderingMode renderingMode = RenderingMode.FULL_EXPAND; @@ -309,6 +311,13 @@ public class PreviewIconFactory { } } } + } else { + if (session.getResult().getException() != null) { + AdtPlugin.log(session.getResult().getException(), + session.getResult().getErrorMessage()); + } else if (session.getResult().getErrorMessage() != null) { + AdtPlugin.log(IStatus.WARNING, session.getResult().getErrorMessage()); + } } session.dispose(); @@ -488,6 +497,19 @@ public class PreviewIconFactory { } private String getFileName(ElementDescriptor descriptor) { + if (descriptor instanceof PaletteMetadataDescriptor) { + PaletteMetadataDescriptor pmd = (PaletteMetadataDescriptor) descriptor; + StringBuilder sb = new StringBuilder(); + String name = pmd.getUiName(); + // Strip out whitespace, parentheses, etc. + for (int i = 0, n = name.length(); i < n; i++) { + char c = name.charAt(i); + if (Character.isLetter(c)) { + sb.append(c); + } + } + return sb.toString() + DOT_PNG; + } return descriptor.getUiName() + DOT_PNG; } @@ -539,7 +561,7 @@ public class PreviewIconFactory { if (themeName.startsWith(themeNamePrefix)) { themeName = themeName.substring(themeNamePrefix.length()); } - String dirName = String.format("palette-preview-r10-%s-%s-%s", cleanup(targetName), + String dirName = String.format("palette-preview-r11-%s-%s-%s", cleanup(targetName), cleanup(themeName), cleanup(mPalette.getCurrentDevice())); IPath dirPath = pluginState.append(dirName); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/PaletteMetadataDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/PaletteMetadataDescriptor.java new file mode 100644 index 0000000..287c5a8 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/PaletteMetadataDescriptor.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2011 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.layout.gre; + +import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME_PREFIX; +import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI; + +import com.android.ide.eclipse.adt.internal.editors.IconFactory; +import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor; +import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SimpleAttribute; +import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SimpleElement; + +import org.eclipse.swt.graphics.Image; +import org.w3c.dom.Element; + +/** + * Special version of {@link ViewElementDescriptor} which is initialized by the palette + * with specific metadata for how to instantiate particular variations of an existing + * {@link ViewElementDescriptor} with initial values. + */ +public class PaletteMetadataDescriptor extends ViewElementDescriptor { + private String mInitString; + private String mIconName; + + public PaletteMetadataDescriptor(ViewElementDescriptor descriptor, String displayName, + String initString, String iconName) { + super(descriptor.getXmlName(), + displayName, + descriptor.getFullClassName(), + descriptor.getTooltip(), + descriptor.getSdkUrl(), + descriptor.getAttributes(), + descriptor.getLayoutAttributes(), + descriptor.getChildren(), descriptor.getMandatory() == Mandatory.MANDATORY); + mInitString = initString; + mIconName = iconName; + } + + /** + * Returns a String which contains a comma separated list of name=value tokens, + * where the name can start with "android:" to indicate a property in the android namespace, + * or no prefix for plain attributes. + * + * @return the initialization string, which can be empty but never null + */ + public String getInitializedAttributes() { + return mInitString != null ? mInitString : ""; //$NON-NLS-1$ + } + + @Override + public Image getIcon() { + if (mIconName != null) { + IconFactory factory = IconFactory.getInstance(); + Image icon = factory.getIcon(mIconName); + if (icon != null) { + return icon; + } + } + + return super.getIcon(); + } + + /** + * Initializes a new {@link SimpleElement} with the palette initialization + * configuration + * + * @param element the new element to initialize + */ + public void initializeNew(SimpleElement element) { + initializeNew(element, null); + } + + /** + * Initializes a new {@link Element} with the palette initialization configuration + * + * @param element the new element to initialize + */ + public void initializeNew(Element element) { + initializeNew(null, element); + } + + private void initializeNew(SimpleElement simpleElement, Element domElement) { + String initializedAttributes = mInitString; + if (initializedAttributes != null && initializedAttributes.length() > 0) { + for (String s : initializedAttributes.split(",")) { //$NON-NLS-1$ + String[] nameValue = s.split("="); //$NON-NLS-1$ + String name = nameValue[0]; + String value = nameValue[1]; + String nameSpace = ""; //$NON-NLS-1$ + if (name.startsWith(ANDROID_NS_NAME_PREFIX)) { + name = name.substring(ANDROID_NS_NAME_PREFIX.length()); + nameSpace = ANDROID_URI; + } + + if (simpleElement != null) { + SimpleAttribute attr = new SimpleAttribute(nameSpace, name, value); + simpleElement.addAttribute(attr); + } + + if (domElement != null) { + domElement.setAttributeNS(nameSpace, name, value); + } + } + } + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ViewMetadataRepository.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ViewMetadataRepository.java index 567f5d5..cf6acba 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ViewMetadataRepository.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ViewMetadataRepository.java @@ -16,7 +16,6 @@ package com.android.ide.eclipse.adt.internal.editors.layout.gre; -import static com.android.ide.common.api.IViewMetadata.FillPreference.NONE; import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI; import static com.android.ide.common.layout.LayoutConstants.ATTR_ID; import static com.android.ide.common.layout.LayoutConstants.ID_PREFIX; @@ -25,6 +24,7 @@ import static com.android.ide.common.layout.LayoutConstants.NEW_ID_PREFIX; import com.android.annotations.VisibleForTesting; import com.android.ide.common.api.IViewMetadata.FillPreference; import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.ide.eclipse.adt.internal.editors.IconFactory; import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors; import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; @@ -41,12 +41,12 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.TreeMap; +import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -149,9 +149,7 @@ public class ViewMetadataRepository { // Therefore, we instead use the convention that the id is the fully qualified // class name, with .'s replaced with _'s. - // Special case: for tab host we aren't allowed to mess with the id - String id = element.getAttributeNS(ANDROID_URI, ATTR_ID); if ("@android:id/tabhost".equals(id)) { @@ -220,29 +218,11 @@ public class ViewMetadataRepository { Node childNode = children.item(j); if (childNode.getNodeType() == Node.ELEMENT_NODE) { Element child = (Element) childNode; - String fqcn = child.getAttribute("class"); //$NON-NLS-1$ - String fill = child.getAttribute("fill"); //$NON-NLS-1$ - FillPreference fillPreference = null; - if (fill.length() > 0) { - fillPreference = fillTypes.get(fill); - } - if (fillPreference == null) { - fillPreference = NONE; - } - String skip = child.getAttribute("skip"); //$NON-NLS-1$ - RenderMode mode = RenderMode.NORMAL; - String render = child.getAttribute("render"); //$NON-NLS-1$ - if (render.length() > 0) { - mode = RenderMode.get(render); - } - String relatedTo = child.getAttribute("relatedTo"); //$NON-NLS-1$ - ViewData view = new ViewData(category, fqcn, fillPreference, - skip.length() == 0 ? false : Boolean.valueOf(skip), - mode, relatedTo); + ViewData view = createViewData(fillTypes, child, + null, FillPreference.NONE, RenderMode.NORMAL); category.addView(view); } } - mCategories.add(category); } } @@ -255,6 +235,62 @@ public class ViewMetadataRepository { return mCategories; } + private ViewData createViewData(Map<String, FillPreference> fillTypes, + Element child, String defaultFqcn, FillPreference defaultFill, + RenderMode defaultRender) { + String fqcn = child.getAttribute("class"); //$NON-NLS-1$ + if (fqcn.length() == 0) { + fqcn = defaultFqcn; + } + String fill = child.getAttribute("fill"); //$NON-NLS-1$ + FillPreference fillPreference = null; + if (fill.length() > 0) { + fillPreference = fillTypes.get(fill); + } + if (fillPreference == null) { + fillPreference = defaultFill; + } + String skip = child.getAttribute("skip"); //$NON-NLS-1$ + RenderMode renderMode = defaultRender; + String render = child.getAttribute("render"); //$NON-NLS-1$ + if (render.length() > 0) { + renderMode = RenderMode.get(render); + } + String displayName = child.getAttribute("name"); //$NON-NLS-1$ + if (displayName.length() == 0) { + displayName = null; + } + String relatedTo = child.getAttribute("relatedTo"); //$NON-NLS-1$ + ViewData view = new ViewData(fqcn, displayName, fillPreference, + skip.length() == 0 ? false : Boolean.valueOf(skip), + renderMode, relatedTo); + + String init = child.getAttribute("init"); //$NON-NLS-1$ + String icon = child.getAttribute("icon"); //$NON-NLS-1$ + + view.setInitString(init); + if (icon.length() > 0) { + view.setIconName(icon); + } + + // Nested variations? + if (child.hasChildNodes()) { + // Palette variations + NodeList childNodes = child.getChildNodes(); + for (int k = 0, kl = childNodes.getLength(); k < kl; k++) { + Node variationNode = childNodes.item(k); + if (variationNode.getNodeType() == Node.ELEMENT_NODE) { + Element variation = (Element) variationNode; + ViewData variationView = createViewData(fillTypes, variation, + fqcn, fillPreference, renderMode); + view.addVariation(variationView); + } + } + } + + return view; + } + /** * Computes the palette entries for the given {@link AndroidTargetData}, looking up the * available node descriptors, categorizing and sorting them. @@ -270,103 +306,87 @@ public class ViewMetadataRepository { List<Pair<String, List<ViewElementDescriptor>>> result = new ArrayList<Pair<String, List<ViewElementDescriptor>>>(); - final Map<String, ViewData> viewMap = getClassToView(); - Map<CategoryData, List<ViewElementDescriptor>> categories = - new TreeMap<CategoryData, List<ViewElementDescriptor>>(); - - // Locate the "Other" category - CategoryData other = null; - for (CategoryData category : getCategories()) { - if (category.getViewCount() == 0) { - other = category; - break; - } - } - List<List<ViewElementDescriptor>> lists = new ArrayList<List<ViewElementDescriptor>>(2); LayoutDescriptors layoutDescriptors = targetData.getLayoutDescriptors(); lists.add(layoutDescriptors.getViewDescriptors()); lists.add(layoutDescriptors.getLayoutDescriptors()); + // First record map of FQCN to ViewElementDescriptor such that we can quickly + // determine if a particular palette entry is available + Map<String, ViewElementDescriptor> fqcnToDescriptor = + new HashMap<String, ViewElementDescriptor>(); for (List<ViewElementDescriptor> list : lists) { for (ViewElementDescriptor view : list) { - ViewData viewData = getClassToView().get(view.getFullClassName()); - CategoryData category = other; - if (viewData != null) { - if (viewData.getSkip()) { - continue; - } - category = viewData.getCategory(); + String fqcn = view.getFullClassName(); + if (fqcn == null) { + // <view> and <merge> tags etc + fqcn = view.getUiName(); } + fqcnToDescriptor.put(fqcn, view); + } + } - List<ViewElementDescriptor> viewList = categories.get(category); - if (viewList == null) { - viewList = new ArrayList<ViewElementDescriptor>(); - categories.put(category, viewList); - } - viewList.add(view); + Set<ViewElementDescriptor> remaining = new HashSet<ViewElementDescriptor>( + layoutDescriptors.getViewDescriptors().size() + + layoutDescriptors.getLayoutDescriptors().size()); + remaining.addAll(layoutDescriptors.getViewDescriptors()); + remaining.addAll(layoutDescriptors.getLayoutDescriptors()); + // Now iterate in palette metadata order over the items in the palette and include + // any that also appear as a descriptor + List<ViewElementDescriptor> categoryItems = new ArrayList<ViewElementDescriptor>(); + for (CategoryData category : getCategories()) { + if (createCategories) { + categoryItems = new ArrayList<ViewElementDescriptor>(); + } + for (ViewData view : category) { + String fqcn = view.getFcqn(); + ViewElementDescriptor descriptor = fqcnToDescriptor.get(fqcn); + if (descriptor != null) { + if (view.getDisplayName() != null || view.getInitString().length() > 0) { + categoryItems.add(new PaletteMetadataDescriptor(descriptor, + view.getDisplayName(), view.getInitString(), view.getIconName())); + } else { + categoryItems.add(descriptor); + } + remaining.remove(descriptor); + + if (view.hasVariations()) { + for (ViewData variation : view.getVariations()) { + String init = variation.getInitString(); + String icon = variation.getIconName(); + ViewElementDescriptor desc = new PaletteMetadataDescriptor(descriptor, + variation.getDisplayName(), init, icon); + categoryItems.add(desc); + } + } + } } - } - if (!createCategories) { - // Squash all categories into a single one, "Views" - Map<CategoryData, List<ViewElementDescriptor>> singleCategory = - new HashMap<CategoryData, List<ViewElementDescriptor>>(); - List<ViewElementDescriptor> items = new ArrayList<ViewElementDescriptor>(100); - for (Map.Entry<CategoryData, List<ViewElementDescriptor>> entry : categories.entrySet()) { - items.addAll(entry.getValue()); + if (createCategories && categoryItems.size() > 0) { + if (alphabetical) { + Collections.sort(categoryItems); + } + result.add(Pair.of(category.getName(), categoryItems)); } - singleCategory.put(new CategoryData("Views"), items); - categories = singleCategory; } - for (Map.Entry<CategoryData, List<ViewElementDescriptor>> entry : categories.entrySet()) { - String name = entry.getKey().getName(); - List<ViewElementDescriptor> items = entry.getValue(); - if (items == null) { - continue; // empty category + if (remaining.size() > 0) { + List<ViewElementDescriptor> otherItems = new ArrayList<ViewElementDescriptor>(remaining); + // Always sorted, we don't have a natural order for these unknowns + Collections.sort(otherItems); + if (createCategories) { + result.add(Pair.of("Other", otherItems)); + } else { + categoryItems.addAll(otherItems); } + } - // Natural sort of the descriptors + if (!createCategories) { if (alphabetical) { - Collections.sort(items); - } else { - Collections.sort(items, new Comparator<ViewElementDescriptor>() { - public int compare(ViewElementDescriptor v1, ViewElementDescriptor v2) { - String fqcn1 = v1.getFullClassName(); - String fqcn2 = v2.getFullClassName(); - if (fqcn1 == null) { - // <view> and <merge> tags etc - fqcn1 = v1.getUiName(); - } - if (fqcn2 == null) { - fqcn2 = v2.getUiName(); - } - ViewData d1 = viewMap.get(fqcn1); - ViewData d2 = viewMap.get(fqcn2); - - // Use natural sorting order of the view data - // Sort unknown views to the end (and alphabetically among themselves) - if (d1 != null) { - if (d2 != null) { - return d1.getOrdinal() - d2.getOrdinal(); - } else { - return 1; - } - } else { - if (d2 == null) { - return v1.getUiName().compareTo(v2.getUiName()); - } else { - return -1; - } - } - } - }); + Collections.sort(categoryItems); } - - - result.add(Pair.of(name, items)); + result.add(Pair.of("Views", categoryItems)); } return result; @@ -404,10 +424,6 @@ public class ViewMetadataRepository { return mName; } - public int getViewCount() { - return mViews.size(); - } - // Implements Iterable<ViewData> such that we can use for-each on the category to // enumerate its views public Iterator<ViewData> iterator() { @@ -426,8 +442,6 @@ public class ViewMetadataRepository { private final String mFqcn; /** Fill preference of the view */ private final FillPreference mFillPreference; - /** The category that the view belongs to */ - private final CategoryData mCategory; /** Skip this item in the palette? */ private final boolean mSkip; /** Must this item be rendered alone? skipped? etc */ @@ -436,25 +450,31 @@ public class ViewMetadataRepository { private final String mRelatedTo; /** The relative rank of the view for natural ordering */ private final int mOrdinal = sNextOrdinal++; + /** List of optional variations */ + private List<ViewData> mVariations; + /** Display name. Can be null. */ + private String mDisplayName; + /** + * Optional initialization string - a comma separate set of name/value pairs to + * initialize the element with + */ + private String mInitString; + /** The name of an icon (known to the {@link IconFactory} to show for this view */ + private String mIconName; /** Constructs a new view data for the given class */ - private ViewData(CategoryData category, String fqcn, + private ViewData(String fqcn, String displayName, FillPreference fillPreference, boolean skip, RenderMode renderMode, String relatedTo) { super(); - mCategory = category; mFqcn = fqcn; + mDisplayName = displayName; mFillPreference = fillPreference; mSkip = skip; mRenderMode = renderMode; mRelatedTo = relatedTo; } - /** Returns the category for views of this type */ - private CategoryData getCategory() { - return mCategory; - } - /** Returns the {@link FillPreference} for views of this type */ private FillPreference getFillPreference() { return mFillPreference; @@ -465,9 +485,8 @@ public class ViewMetadataRepository { return mFqcn; } - /** Relative rank of this view type */ - private int getOrdinal() { - return mOrdinal; + private String getDisplayName() { + return mDisplayName; } // Implements Comparable<ViewData> such that views can be sorted naturally @@ -509,6 +528,37 @@ public class ViewMetadataRepository { return result; } } + + void addVariation(ViewData variation) { + if (mVariations == null) { + mVariations = new ArrayList<ViewData>(4); + } + mVariations.add(variation); + } + + List<ViewData> getVariations() { + return mVariations; + } + + boolean hasVariations() { + return mVariations != null && mVariations.size() > 0; + } + + private void setInitString(String initString) { + this.mInitString = initString; + } + + private String getInitString() { + return mInitString; + } + + private void setIconName(String iconName) { + this.mIconName = iconName; + } + + private String getIconName() { + return mIconName; + } } /** @@ -540,7 +590,7 @@ public class ViewMetadataRepository { return view.getRenderMode(); } - return RenderMode.ALONE; + return RenderMode.NORMAL; } /** diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml index 262f63d..96e9a01 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/extra-view-metadata.xml @@ -15,9 +15,12 @@ <!ATTLIST category name CDATA #IMPLIED> <!--- Each view is identified by its full class name and has various other attributes such as a fill preference --> -<!ELEMENT view EMPTY> +<!ELEMENT view (view)*> <!ATTLIST view - class CDATA #REQUIRED + class CDATA #IMPLIED + name CDATA #IMPLIED + init CDATA #IMPLIED + icon CDATA #IMPLIED relatedTo CDATA #IMPLIED skip (true|false) "false" render (alone|skip|normal) "normal" @@ -35,12 +38,12 @@ class="android.widget.Button" relatedTo="ImageButton" /> <view - class="android.widget.CheckBox" - relatedTo="RadioButton,ToggleButton,CheckedTextView" /> - <view class="android.widget.ToggleButton" relatedTo="CheckBox" /> <view + class="android.widget.CheckBox" + relatedTo="RadioButton,ToggleButton,CheckedTextView" /> + <view class="android.widget.RadioButton" relatedTo="CheckBox,ToggleButton" /> <view @@ -55,33 +58,95 @@ relatedTo="Spinner,TextView,AutoCompleteTextView,MultiAutoCompleteTextView" fill="width_in_vertical" /> <view - class="android.widget.AutoCompleteTextView" - relatedTo="EditText,MultiAutoCompleteTextView" - fill="width_in_vertical" /> + class="android.widget.ProgressBar" + relatedTo="SeekBar" + name="ProgressBar (Large)" + init="style=?android:attr/progressBarStyleLarge"> + <view + name="ProgressBar (Normal)" + init="" /> + <view + name="ProgressBar (Small)" + init="style=?android:attr/progressBarStyleSmall" /> + <view + name="ProgressBar (Horizontal)" + init="style=?android:attr/progressBarStyleHorizontal" /> + </view> <view - class="android.widget.MultiAutoCompleteTextView" - relatedTo="EditText,AutoCompleteTextView" + class="android.widget.SeekBar" + relatedTo="ProgressBar" fill="width_in_vertical" /> <view - class="android.widget.ProgressBar" - relatedTo="SeekBar" /> - <view class="android.widget.QuickContactBadge" /> <view class="android.widget.RadioGroup" /> <view class="android.widget.RatingBar" /> + </category> + <category + name="Text Fields"> <view - class="android.widget.SeekBar" - relatedTo="ProgressBar" + class="android.widget.EditText" + name="Plain Text" + init="" + relatedTo="Spinner,TextView,AutoCompleteTextView,MultiAutoCompleteTextView" + fill="width_in_vertical"> + <view + name="Person Name" + init="android:inputType=textPersonName" /> + <view + name="Password" + init="android:inputType=textPassword" /> + <view + name="Password (Numeric)" + init="android:inputType=numberPassword" /> + <view + name="E-mail" + init="android:inputType=textEmailAddress" /> + <view + name="Phone" + init="android:inputType=phone" /> + <view + name="Postal Address" + init="android:inputType=textPostalAddress" /> + <view + name="Multiline Text" + init="android:inputType=textMultiLine" /> + <view + name="Time" + init="android:inputType=time" /> + <view + name="Date" + init="android:inputType=date" /> + <view + name="Number" + init="android:inputType=number" /> + <view + name="Number (Signed)" + init="android:inputType=numberSigned" /> + <view + name="Number (Decimal)" + init="android:inputType=numberDecimal" /> + </view> + <view + class="android.widget.AutoCompleteTextView" + fill="width_in_vertical" /> + <view + class="android.widget.MultiAutoCompleteTextView" fill="width_in_vertical" /> </category> <category name="Layouts"> <view class="android.widget.LinearLayout" + name="LinearLayout (Vertical)" + init="android:orientation=vertical" + icon="VerticalLinearLayout" fill="opposite" - render="skip" /> + render="skip"> + <view + name="LinearLayout (Horizontal)" /> + </view> <view class="android.widget.RelativeLayout" fill="opposite" @@ -266,4 +331,4 @@ <!-- This is the catch-all category which contains unknown views if we encounter any --> </category> <!-- TODO: Add-ons? --> -</metadata>
\ No newline at end of file +</metadata> diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/rendering-configs.xml b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/rendering-configs.xml index 9c99644..3eaac16 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/rendering-configs.xml +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/rendering-configs.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Default configuration for various views to be rendered + Default configuration for various views to be rendered TODO: Remove views that don't have custom configuration TODO: Parameterize the custom width (200dip) in the below? --> @@ -57,6 +57,110 @@ android:text="EditText" android:layout_width="200dip"> </EditText> + + <EditText + android:id="@+id/PlainText" + android:text="abc" + android:layout_width="200dip" + android:layout_height="wrap_content"> + </EditText> + + <EditText + android:id="@+id/Password" + android:inputType="textPassword" + android:text="••••••••" + android:layout_width="200dip" + android:layout_height="wrap_content"> + </EditText> + + <!-- android:inputType="numberPassword" not used here to allow digits in preview only --> + <EditText + android:id="@+id/PasswordNumeric" + android:text="1•••2•••3" + android:layout_width="200dip" + android:layout_height="wrap_content"> + </EditText> + + <EditText + android:id="@+id/PersonName" + android:inputType="textPersonName" + android:text="Firstname Lastname" + android:layout_width="200dip" + android:layout_height="wrap_content"> + </EditText> + + <EditText + android:id="@+id/Phone" + android:inputType="phone" + android:text="(555) 0100" + android:layout_width="200dip" + android:layout_height="wrap_content"> + </EditText> + + <EditText + android:id="@+id/PostalAddress" + android:inputType="textPostalAddress" + android:text="Address" + android:layout_width="200dip" + android:layout_height="100dip"> + </EditText> + + <EditText + android:id="@+id/MultilineText" + android:inputType="textMultiLine" + android:text="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor" + android:layout_width="200dip" + android:layout_height="100dip"> + </EditText> + + <EditText + android:id="@+id/Date" + android:inputType="date" + android:text="1/1/2011" + android:layout_width="200dip" + android:layout_height="wrap_content"> + </EditText> + + <EditText + android:id="@+id/Time" + android:inputType="time" + android:text="12:00am" + android:layout_width="200dip" + android:layout_height="wrap_content"> + </EditText> + + <EditText + android:id="@+id/Email" + android:inputType="textEmailAddress" + android:text="user@domain" + android:layout_width="200dip" + android:layout_height="wrap_content"> + </EditText> + + <EditText + android:id="@+id/Number" + android:inputType="number" + android:text="42" + android:layout_width="200dip" + android:layout_height="wrap_content"> + </EditText> + + <EditText + android:id="@+id/NumberSigned" + android:inputType="numberSigned" + android:text="-42" + android:layout_width="200dip" + android:layout_height="wrap_content"> + </EditText> + + <EditText + android:id="@+id/NumberDecimal" + android:inputType="numberDecimal" + android:text="42.0" + android:layout_width="200dip" + android:layout_height="wrap_content"> + </EditText> + <ImageButton android:layout_height="wrap_content" android:layout_width="wrap_content" @@ -76,10 +180,29 @@ android:id="@+id/android_widget_MultiAutoCompleteTextView"> </MultiAutoCompleteTextView> <ProgressBar - android:id="@+id/android_widget_ProgressBar" + android:id="@+id/android_widget_ProgressBarNormal" android:layout_width="wrap_content" android:layout_height="wrap_content"> </ProgressBar> + <ProgressBar + android:id="@+id/android_widget_ProgressBarHorizontal" + android:layout_width="200dip" + android:layout_height="wrap_content" + android:progress="30" + style="?android:attr/progressBarStyleHorizontal"> + </ProgressBar> + <ProgressBar + android:id="@+id/android_widget_ProgressBarLarge" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + style="?android:attr/progressBarStyleLarge"> + </ProgressBar> + <ProgressBar + android:id="@+id/android_widget_ProgressBarSmall" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + style="?android:attr/progressBarStyleSmall"> + </ProgressBar> <QuickContactBadge android:layout_height="wrap_content" android:layout_width="wrap_content" diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ExtractIncludeRefactoring.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ExtractIncludeRefactoring.java index cb2a25c..d5921bf 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ExtractIncludeRefactoring.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ExtractIncludeRefactoring.java @@ -15,7 +15,7 @@ */ package com.android.ide.eclipse.adt.internal.editors.layout.refactoring; -import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_PREFIX; +import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME; import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI; import static com.android.ide.common.layout.LayoutConstants.ATTR_ID; import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_HEIGHT; @@ -350,7 +350,7 @@ public class ExtractIncludeRefactoring extends VisualRefactoring { namespaceDeclarations = sb.toString(); if (androidNsPrefix == null) { - androidNsPrefix = ANDROID_NS_PREFIX; + androidNsPrefix = ANDROID_NS_NAME; } if (namespaceDeclarations.length() == 0) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/VisualRefactoring.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/VisualRefactoring.java index e496b7a..3cce3b3 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/VisualRefactoring.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/VisualRefactoring.java @@ -15,7 +15,7 @@ */ package com.android.ide.eclipse.adt.internal.editors.layout.refactoring; -import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_PREFIX; +import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME; import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI; import static com.android.ide.common.layout.LayoutConstants.ANDROID_WIDGET_PREFIX; import static com.android.ide.common.layout.LayoutConstants.ATTR_ID; @@ -521,7 +521,7 @@ public abstract class VisualRefactoring extends Refactoring { } if (mAndroidNamespacePrefix == null) { - mAndroidNamespacePrefix = ANDROID_NS_PREFIX; + mAndroidNamespacePrefix = ANDROID_NS_NAME; } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java index f4b10b7..60b5662 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java @@ -112,7 +112,7 @@ public class UiViewElementNode extends UiElementNode { layout_attrs.length); if (need_xmlns) { AttributeDescriptor desc = new XmlnsAttributeDescriptor( - LayoutConstants.ANDROID_NS_PREFIX, + LayoutConstants.ANDROID_NS_NAME, SdkConstants.NS_RESOURCES); mCachedAttributeDescriptors[direct_attrs.length + layout_attrs.length] = desc; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/menu/descriptors/MenuDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/menu/descriptors/MenuDescriptors.java index a84c743..f093a9b 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/menu/descriptors/MenuDescriptors.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/menu/descriptors/MenuDescriptors.java @@ -16,7 +16,7 @@ package com.android.ide.eclipse.adt.internal.editors.menu.descriptors; -import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_PREFIX; +import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME; import com.android.ide.common.resources.platform.DeclareStyleableInfo; import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor; @@ -122,7 +122,7 @@ public final class MenuDescriptors implements IDescriptorProvider { new ElementDescriptor[] { top_item }, // childrenElements, false /* mandatory */); - XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(ANDROID_NS_PREFIX, + XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(ANDROID_NS_NAME, SdkConstants.NS_RESOURCES); updateElement(mDescriptor, styleMap, "Menu", xmlns); //$NON-NLS-1$ diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiElementNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiElementNode.java index 01d4e4e..1a66cdb 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiElementNode.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiElementNode.java @@ -16,7 +16,7 @@ package com.android.ide.eclipse.adt.internal.editors.uimodel; -import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_PREFIX; +import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME; import static com.android.ide.common.layout.LayoutConstants.ID_PREFIX; import static com.android.ide.common.layout.LayoutConstants.NEW_ID_PREFIX; import static com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor.XMLNS; @@ -1592,7 +1592,7 @@ public class UiElementNode implements IPropertySource { // We need to make sure the prefix is not one that was declared in the scope // visited above. Use a default namespace prefix "android" for the Android resource // NS and use "ns" for all other custom namespaces. - String prefix = NS_RESOURCES.equals(nsUri) ? ANDROID_NS_PREFIX : "ns"; //$NON-NLS-1$ + String prefix = NS_RESOURCES.equals(nsUri) ? ANDROID_NS_NAME : "ns"; //$NON-NLS-1$ String base = prefix; for (int i = 1; visited.contains(prefix); i++) { prefix = base + Integer.toString(i); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiListAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiListAttributeNode.java index cdb0c9a..c8e5720 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiListAttributeNode.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiListAttributeNode.java @@ -140,7 +140,7 @@ public class UiListAttributeNode extends UiAbstractTextAttributeNode { // FrameworkResourceManager expects a specific prefix for the attribute. String nsPrefix = ""; if (SdkConstants.NS_RESOURCES.equals(descriptor.getNamespaceUri())) { - nsPrefix = LayoutConstants.ANDROID_NS_PREFIX + ':'; + nsPrefix = LayoutConstants.ANDROID_NS_NAME + ':'; } else if (XmlnsAttributeDescriptor.XMLNS_URI.equals(descriptor.getNamespaceUri())) { nsPrefix = XmlnsAttributeDescriptor.XMLNS_COLON; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java index 43c8fcd..b10d69b 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiResourceAttributeNode.java @@ -16,6 +16,8 @@ package com.android.ide.eclipse.adt.internal.editors.uimodel; +import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME_PREFIX; + import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor; import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils; @@ -200,7 +202,7 @@ public class UiResourceAttributeNode extends UiTextAttributeNode { UiElementNode uiNode = getUiParent(); AndroidXmlEditor editor = uiNode.getEditor(); - if (prefix == null || prefix.indexOf("android:") < 0) { //$NON-NLS-1$ + if (prefix == null || !prefix.contains(ANDROID_NS_NAME_PREFIX)) { IProject project = editor.getProject(); if (project != null) { // get the resource repository for this project and the system resources. @@ -257,7 +259,7 @@ public class UiResourceAttributeNode extends UiTextAttributeNode { } if (isSystem) { - sb.append("android:"); //$NON-NLS-1$ + sb.append(ANDROID_NS_NAME_PREFIX); } sb.append(typeName).append('/'); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/descriptors/XmlDescriptors.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/descriptors/XmlDescriptors.java index b807aa1..bc74d57 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/descriptors/XmlDescriptors.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/xml/descriptors/XmlDescriptors.java @@ -16,7 +16,7 @@ package com.android.ide.eclipse.adt.internal.editors.xml.descriptors; -import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_PREFIX; +import static com.android.ide.common.layout.LayoutConstants.ANDROID_NS_NAME; import com.android.ide.common.resources.platform.AttributeInfo; import com.android.ide.common.resources.platform.DeclareStyleableInfo; @@ -134,7 +134,7 @@ public final class XmlDescriptors implements IDescriptorProvider { ViewClassInfo[] prefs, ViewClassInfo[] prefGroups) { XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor( - ANDROID_NS_PREFIX, + ANDROID_NS_NAME, SdkConstants.NS_RESOURCES); ElementDescriptor searchable = createSearchable(searchableStyleMap, xmlns); diff --git a/monkeyrunner/src/com/android/monkeyrunner/MonkeyImage.java b/monkeyrunner/src/com/android/monkeyrunner/MonkeyImage.java index d506613..70201ee 100644 --- a/monkeyrunner/src/com/android/monkeyrunner/MonkeyImage.java +++ b/monkeyrunner/src/com/android/monkeyrunner/MonkeyImage.java @@ -32,6 +32,8 @@ import java.io.File; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.Iterator; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.imageio.ImageIO; import javax.imageio.ImageWriter; @@ -42,6 +44,8 @@ import javax.imageio.stream.ImageOutputStream; */ @MonkeyRunnerExported(doc = "An image") public abstract class MonkeyImage extends PyObject implements ClassDictInit { + private static Logger LOG = Logger.getLogger(MonkeyImage.class.getCanonicalName()); + public static void classDictInit(PyObject dict) { JythonUtils.convertDocAnnotationsForClass(MonkeyImage.class, dict); } @@ -130,7 +134,7 @@ public abstract class MonkeyImage extends PyObject implements ClassDictInit { return writeToFile(path, "png"); } ImageWriter writer = writers.next(); - BufferedImage image = getBufferedImage(); + BufferedImage image = convertSnapshot(); try { File f = new File(path); f.delete(); @@ -273,7 +277,26 @@ public abstract class MonkeyImage extends PyObject implements ClassDictInit { public BufferedImage createBufferedImage() { return image; } + } + /* package */ static MonkeyImage loadImageFromFile(String path) { + File f = new File(path); + if (f.exists() && f.canRead()) { + try { + BufferedImage bufferedImage = ImageIO.read(new File(path)); + if (bufferedImage == null) { + LOG.log(Level.WARNING, "Cannot decode file %s", path); + return null; + } + return new BufferedImageMonkeyImage(bufferedImage); + } catch (IOException e) { + LOG.log(Level.WARNING, "Exception trying to decode image", e); + return null; + } + } else { + LOG.log(Level.WARNING, "Cannot read file %s", path); + return null; + } } @MonkeyRunnerExported(doc = "Copy a rectangular region of the image.", @@ -295,4 +318,4 @@ public abstract class MonkeyImage extends PyObject implements ClassDictInit { BufferedImage image = getBufferedImage(); return new BufferedImageMonkeyImage(image.getSubimage(x, y, w, h)); } -} +}
\ No newline at end of file diff --git a/monkeyrunner/src/com/android/monkeyrunner/MonkeyRunner.java b/monkeyrunner/src/com/android/monkeyrunner/MonkeyRunner.java index 8480223..5f137cd 100644 --- a/monkeyrunner/src/com/android/monkeyrunner/MonkeyRunner.java +++ b/monkeyrunner/src/com/android/monkeyrunner/MonkeyRunner.java @@ -174,6 +174,21 @@ public class MonkeyRunner extends PyObject implements ClassDictInit { return choice(message, title, choices); } + @MonkeyRunnerExported(doc = "Loads a MonkeyImage from a file.", + args = { "path" }, + argDocs = { + "The path to the file to load. This file path is in terms of the computer running " + + "MonkeyRunner and not a path on the Android Device. " }, + returns = "A new MonkeyImage representing the specified file") + public static MonkeyImage loadImageFromFile(PyObject[] args, String kws[]) { + ArgParser ap = JythonUtils.createArgParser(args, kws); + Preconditions.checkNotNull(ap); + + String path = ap.getString(0); + + return MonkeyImage.loadImageFromFile(path); + } + /** * Display an alert dialog. * |