aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/UiElementPullParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/UiElementPullParser.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/UiElementPullParser.java661
1 files changed, 0 insertions, 661 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/UiElementPullParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/UiElementPullParser.java
deleted file mode 100644
index 858156884..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/UiElementPullParser.java
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- * 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.layout;
-
-import static com.android.SdkConstants.ANDROID_URI;
-import static com.android.SdkConstants.ATTR_LAYOUT;
-import static com.android.SdkConstants.ATTR_LAYOUT_HEIGHT;
-import static com.android.SdkConstants.ATTR_LAYOUT_WIDTH;
-import static com.android.SdkConstants.ATTR_PADDING;
-import static com.android.SdkConstants.AUTO_URI;
-import static com.android.SdkConstants.UNIT_DIP;
-import static com.android.SdkConstants.UNIT_DP;
-import static com.android.SdkConstants.UNIT_IN;
-import static com.android.SdkConstants.UNIT_MM;
-import static com.android.SdkConstants.UNIT_PT;
-import static com.android.SdkConstants.UNIT_PX;
-import static com.android.SdkConstants.UNIT_SP;
-import static com.android.SdkConstants.VALUE_FILL_PARENT;
-import static com.android.SdkConstants.VALUE_MATCH_PARENT;
-import static com.android.SdkConstants.VIEW_FRAGMENT;
-import static com.android.SdkConstants.VIEW_INCLUDE;
-
-import com.android.ide.common.rendering.api.ILayoutPullParser;
-import com.android.ide.common.rendering.api.ViewInfo;
-import com.android.ide.common.res2.ValueXmlHelper;
-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.editors.layout.gle2.FragmentMenu;
-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.sdk.AndroidTargetData;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.resources.Density;
-import com.android.sdklib.IAndroidTarget;
-
-import org.eclipse.core.resources.IProject;
-import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * {@link ILayoutPullParser} implementation on top of {@link UiElementNode}.
- * <p/>
- * It's designed to work on layout files, and will most likely not work on other resource files.
- * <p/>
- * This pull parser generates {@link ViewInfo}s which key is a {@link UiElementNode}.
- */
-public class UiElementPullParser extends BasePullParser {
- private final static Pattern FLOAT_PATTERN = Pattern.compile("(-?[0-9]+(?:\\.[0-9]+)?)(.*)"); //$NON-NLS-1$
-
- private final int[] sIntOut = new int[1];
-
- private final ArrayList<UiElementNode> mNodeStack = new ArrayList<UiElementNode>();
- private UiElementNode mRoot;
- private final boolean mExplodedRendering;
- private boolean mZeroAttributeIsPadding = false;
- private boolean mIncreaseExistingPadding = false;
- private LayoutDescriptors mDescriptors;
- private final Density mDensity;
-
- /**
- * Number of pixels to pad views with in exploded-rendering mode.
- */
- private static final String DEFAULT_PADDING_VALUE =
- ExplodedRenderingHelper.PADDING_VALUE + UNIT_PX;
-
- /**
- * Number of pixels to pad exploded individual views with. (This is HALF the width of the
- * rectangle since padding is repeated on both sides of the empty content.)
- */
- private static final String FIXED_PADDING_VALUE = "20px"; //$NON-NLS-1$
-
- /**
- * Set of nodes that we want to auto-pad using {@link #FIXED_PADDING_VALUE} as the padding
- * attribute value. Can be null, which is the case when we don't want to perform any
- * <b>individual</b> node exploding.
- */
- private final Set<UiElementNode> mExplodeNodes;
-
- /**
- * Constructs a new {@link UiElementPullParser}, a parser dedicated to the special case of
- * parsing a layout resource files, and handling "exploded rendering" - adding padding on views
- * to make them easier to see and operate on.
- *
- * @param top The {@link UiElementNode} for the root node.
- * @param explodeRendering When true, add padding to <b>all</b> nodes in the hierarchy. This
- * will add rather than replace padding of a node.
- * @param explodeNodes A set of individual nodes that should be assigned a fixed amount of
- * padding ({@link #FIXED_PADDING_VALUE}). This is intended for use with nodes that
- * (without padding) would be invisible. This parameter can be null, in which case
- * nodes are not individually exploded (but they may all be exploded with the
- * explodeRendering parameter.
- * @param density the density factor for the screen.
- * @param project Project containing this layout.
- */
- public UiElementPullParser(UiElementNode top, boolean explodeRendering,
- Set<UiElementNode> explodeNodes,
- Density density, IProject project) {
- super();
- mRoot = top;
- mExplodedRendering = explodeRendering;
- mExplodeNodes = explodeNodes;
- mDensity = density;
- if (mExplodedRendering) {
- // get the layout descriptor
- IAndroidTarget target = Sdk.getCurrent().getTarget(project);
- AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
- mDescriptors = data.getLayoutDescriptors();
- }
- push(mRoot);
- }
-
- protected UiElementNode getCurrentNode() {
- if (mNodeStack.size() > 0) {
- return mNodeStack.get(mNodeStack.size()-1);
- }
-
- return null;
- }
-
- private Node getAttribute(int i) {
- if (mParsingState != START_TAG) {
- throw new IndexOutOfBoundsException();
- }
-
- // get the current uiNode
- UiElementNode uiNode = getCurrentNode();
-
- // get its xml node
- Node xmlNode = uiNode.getXmlNode();
-
- if (xmlNode != null) {
- return xmlNode.getAttributes().item(i);
- }
-
- return null;
- }
-
- private void push(UiElementNode node) {
- mNodeStack.add(node);
-
- mZeroAttributeIsPadding = false;
- mIncreaseExistingPadding = false;
-
- if (mExplodedRendering) {
- // first get the node name
- String xml = node.getDescriptor().getXmlLocalName();
- ViewElementDescriptor descriptor = mDescriptors.findDescriptorByTag(xml);
- if (descriptor != null) {
- NamedNodeMap attributes = node.getXmlNode().getAttributes();
- Node padding = attributes.getNamedItemNS(ANDROID_URI, ATTR_PADDING);
- if (padding == null) {
- // we'll return an extra padding
- mZeroAttributeIsPadding = true;
- } else {
- mIncreaseExistingPadding = true;
- }
- }
- }
- }
-
- private UiElementNode pop() {
- return mNodeStack.remove(mNodeStack.size()-1);
- }
-
- // ------------- IXmlPullParser --------
-
- /**
- * {@inheritDoc}
- * <p/>
- * This implementation returns the underlying DOM node of type {@link UiElementNode}.
- * Note that the link between the GLE and the parsing code depends on this being the actual
- * type returned, so you can't just randomly change it here.
- * <p/>
- * Currently used by:
- * - private method GraphicalLayoutEditor#updateNodeWithBounds(ILayoutViewInfo).
- * - private constructor of LayoutCanvas.CanvasViewInfo.
- */
- @Override
- public Object getViewCookie() {
- return getCurrentNode();
- }
-
- /**
- * Legacy method required by {@link com.android.layoutlib.api.IXmlPullParser}
- */
- @Override
- public Object getViewKey() {
- return getViewCookie();
- }
-
- /**
- * This implementation does nothing for now as all the embedded XML will use a normal KXML
- * parser.
- */
- @Override
- public ILayoutPullParser getParser(String layoutName) {
- return null;
- }
-
- // ------------- XmlPullParser --------
-
- @Override
- public String getPositionDescription() {
- return "XML DOM element depth:" + mNodeStack.size();
- }
-
- /*
- * This does not seem to be called by the layoutlib, but we keep this (and maintain
- * it) just in case.
- */
- @Override
- public int getAttributeCount() {
- UiElementNode node = getCurrentNode();
-
- if (node != null) {
- Collection<UiAttributeNode> attributes = node.getAllUiAttributes();
- int count = attributes.size();
-
- return count + (mZeroAttributeIsPadding ? 1 : 0);
- }
-
- return 0;
- }
-
- /*
- * This does not seem to be called by the layoutlib, but we keep this (and maintain
- * it) just in case.
- */
- @Override
- public String getAttributeName(int i) {
- if (mZeroAttributeIsPadding) {
- if (i == 0) {
- return ATTR_PADDING;
- } else {
- i--;
- }
- }
-
- Node attribute = getAttribute(i);
- if (attribute != null) {
- return attribute.getLocalName();
- }
-
- return null;
- }
-
- /*
- * This does not seem to be called by the layoutlib, but we keep this (and maintain
- * it) just in case.
- */
- @Override
- public String getAttributeNamespace(int i) {
- if (mZeroAttributeIsPadding) {
- if (i == 0) {
- return ANDROID_URI;
- } else {
- i--;
- }
- }
-
- Node attribute = getAttribute(i);
- if (attribute != null) {
- return attribute.getNamespaceURI();
- }
- return ""; //$NON-NLS-1$
- }
-
- /*
- * This does not seem to be called by the layoutlib, but we keep this (and maintain
- * it) just in case.
- */
- @Override
- public String getAttributePrefix(int i) {
- if (mZeroAttributeIsPadding) {
- if (i == 0) {
- // figure out the prefix associated with the android namespace.
- Document doc = mRoot.getXmlDocument();
- return doc.lookupPrefix(ANDROID_URI);
- } else {
- i--;
- }
- }
-
- Node attribute = getAttribute(i);
- if (attribute != null) {
- return attribute.getPrefix();
- }
- return null;
- }
-
- /*
- * This does not seem to be called by the layoutlib, but we keep this (and maintain
- * it) just in case.
- */
- @Override
- public String getAttributeValue(int i) {
- if (mZeroAttributeIsPadding) {
- if (i == 0) {
- return DEFAULT_PADDING_VALUE;
- } else {
- i--;
- }
- }
-
- Node attribute = getAttribute(i);
- if (attribute != null) {
- String value = attribute.getNodeValue();
- if (mIncreaseExistingPadding && ATTR_PADDING.equals(attribute.getLocalName()) &&
- ANDROID_URI.equals(attribute.getNamespaceURI())) {
- // add the padding and return the value
- return addPaddingToValue(value);
- }
- return value;
- }
-
- return null;
- }
-
- /*
- * This is the main method used by the LayoutInflater to query for attributes.
- */
- @Override
- public String getAttributeValue(String namespace, String localName) {
- if (mExplodeNodes != null && ATTR_PADDING.equals(localName) &&
- ANDROID_URI.equals(namespace)) {
- UiElementNode node = getCurrentNode();
- if (node != null && mExplodeNodes.contains(node)) {
- return FIXED_PADDING_VALUE;
- }
- }
-
- if (mZeroAttributeIsPadding && ATTR_PADDING.equals(localName) &&
- ANDROID_URI.equals(namespace)) {
- return DEFAULT_PADDING_VALUE;
- }
-
- // get the current uiNode
- UiElementNode uiNode = getCurrentNode();
-
- // get its xml node
- Node xmlNode = uiNode.getXmlNode();
-
- if (xmlNode != null) {
- if (ATTR_LAYOUT.equals(localName) && VIEW_FRAGMENT.equals(xmlNode.getNodeName())) {
- String layout = FragmentMenu.getFragmentLayout(xmlNode);
- if (layout != null) {
- return layout;
- }
- }
-
- Node attribute = xmlNode.getAttributes().getNamedItemNS(namespace, localName);
-
- // Auto-convert http://schemas.android.com/apk/res-auto resources. The lookup
- // will be for the current application's resource package, e.g.
- // http://schemas.android.com/apk/res/foo.bar, but the XML document will
- // be using http://schemas.android.com/apk/res-auto in library projects:
- if (attribute == null && namespace != null && !namespace.equals(ANDROID_URI)) {
- attribute = xmlNode.getAttributes().getNamedItemNS(AUTO_URI, localName);
- }
-
- if (attribute != null) {
- String value = attribute.getNodeValue();
- if (mIncreaseExistingPadding && ATTR_PADDING.equals(localName) &&
- ANDROID_URI.equals(namespace)) {
- // add the padding and return the value
- return addPaddingToValue(value);
- }
-
- // on the fly convert match_parent to fill_parent for compatibility with older
- // platforms.
- if (VALUE_MATCH_PARENT.equals(value) &&
- (ATTR_LAYOUT_WIDTH.equals(localName) ||
- ATTR_LAYOUT_HEIGHT.equals(localName)) &&
- ANDROID_URI.equals(namespace)) {
- return VALUE_FILL_PARENT;
- }
-
- // Handle unicode escapes etc
- value = ValueXmlHelper.unescapeResourceString(value, false, false);
-
- return value;
- }
- }
-
- return null;
- }
-
- @Override
- public int getDepth() {
- return mNodeStack.size();
- }
-
- @Override
- public String getName() {
- if (mParsingState == START_TAG || mParsingState == END_TAG) {
- String name = getCurrentNode().getDescriptor().getXmlLocalName();
-
- if (name.equals(VIEW_FRAGMENT)) {
- // Temporarily translate <fragment> to <include> (and in getAttribute
- // we will also provide a layout-attribute for the corresponding
- // fragment name attribute)
- String layout = FragmentMenu.getFragmentLayout(getCurrentNode().getXmlNode());
- if (layout != null) {
- return VIEW_INCLUDE;
- }
- }
-
- return name;
- }
-
- return null;
- }
-
- @Override
- public String getNamespace() {
- if (mParsingState == START_TAG || mParsingState == END_TAG) {
- return getCurrentNode().getDescriptor().getNamespace();
- }
-
- return null;
- }
-
- @Override
- public String getPrefix() {
- if (mParsingState == START_TAG || mParsingState == END_TAG) {
- Document doc = mRoot.getXmlDocument();
- return doc.lookupPrefix(getCurrentNode().getDescriptor().getNamespace());
- }
-
- return null;
- }
-
- @Override
- public boolean isEmptyElementTag() throws XmlPullParserException {
- if (mParsingState == START_TAG) {
- return getCurrentNode().getUiChildren().size() == 0;
- }
-
- throw new XmlPullParserException("Call to isEmptyElementTag while not in START_TAG",
- this, null);
- }
-
- @Override
- public void onNextFromStartDocument() {
- onNextFromStartTag();
- }
-
- @Override
- public void onNextFromStartTag() {
- // get the current node, and look for text or children (children first)
- UiElementNode node = getCurrentNode();
- List<UiElementNode> children = node.getUiChildren();
- if (children.size() > 0) {
- // move to the new child, and don't change the state.
- push(children.get(0));
-
- // in case the current state is CURRENT_DOC, we set the proper state.
- mParsingState = START_TAG;
- } else {
- if (mParsingState == START_DOCUMENT) {
- // this handles the case where there's no node.
- mParsingState = END_DOCUMENT;
- } else {
- mParsingState = END_TAG;
- }
- }
- }
-
- @Override
- public void onNextFromEndTag() {
- // look for a sibling. if no sibling, go back to the parent
- UiElementNode node = getCurrentNode();
- node = node.getUiNextSibling();
- if (node != null) {
- // to go to the sibling, we need to remove the current node,
- pop();
- // and add its sibling.
- push(node);
- mParsingState = START_TAG;
- } else {
- // move back to the parent
- pop();
-
- // we have only one element left (mRoot), then we're done with the document.
- if (mNodeStack.size() == 1) {
- mParsingState = END_DOCUMENT;
- } else {
- mParsingState = END_TAG;
- }
- }
- }
-
- // ------- TypedValue stuff
- // This is adapted from com.android.layoutlib.bridge.ResourceHelper
- // (but modified to directly take the parsed value and convert it into pixel instead of
- // storing it into a TypedValue)
- // this was originally taken from platform/frameworks/base/libs/utils/ResourceTypes.cpp
-
- private static final class DimensionEntry {
- String name;
- int type;
-
- DimensionEntry(String name, int unit) {
- this.name = name;
- this.type = unit;
- }
- }
-
- /** {@link DimensionEntry} complex unit: Value is raw pixels. */
- private static final int COMPLEX_UNIT_PX = 0;
- /** {@link DimensionEntry} complex unit: Value is Device Independent
- * Pixels. */
- private static final int COMPLEX_UNIT_DIP = 1;
- /** {@link DimensionEntry} complex unit: Value is a scaled pixel. */
- private static final int COMPLEX_UNIT_SP = 2;
- /** {@link DimensionEntry} complex unit: Value is in points. */
- private static final int COMPLEX_UNIT_PT = 3;
- /** {@link DimensionEntry} complex unit: Value is in inches. */
- private static final int COMPLEX_UNIT_IN = 4;
- /** {@link DimensionEntry} complex unit: Value is in millimeters. */
- private static final int COMPLEX_UNIT_MM = 5;
-
- private final static DimensionEntry[] sDimensions = new DimensionEntry[] {
- new DimensionEntry(UNIT_PX, COMPLEX_UNIT_PX),
- new DimensionEntry(UNIT_DIP, COMPLEX_UNIT_DIP),
- new DimensionEntry(UNIT_DP, COMPLEX_UNIT_DIP),
- new DimensionEntry(UNIT_SP, COMPLEX_UNIT_SP),
- new DimensionEntry(UNIT_PT, COMPLEX_UNIT_PT),
- new DimensionEntry(UNIT_IN, COMPLEX_UNIT_IN),
- new DimensionEntry(UNIT_MM, COMPLEX_UNIT_MM),
- };
-
- /**
- * Adds padding to an existing dimension.
- * <p/>This will resolve the attribute value (which can be px, dip, dp, sp, pt, in, mm) to
- * a pixel value, add the padding value ({@link ExplodedRenderingHelper#PADDING_VALUE}),
- * and then return a string with the new value as a px string ("42px");
- * If the conversion fails, only the special padding is returned.
- */
- private String addPaddingToValue(String s) {
- int padding = ExplodedRenderingHelper.PADDING_VALUE;
- if (stringToPixel(s)) {
- padding += sIntOut[0];
- }
-
- return padding + UNIT_PX;
- }
-
- /**
- * Convert the string into a pixel value, and puts it in {@link #sIntOut}
- * @param s the dimension value from an XML attribute
- * @return true if success.
- */
- private boolean stringToPixel(String s) {
- // remove the space before and after
- s = s.trim();
- int len = s.length();
-
- if (len <= 0) {
- return false;
- }
-
- // check that there's no non ASCII characters.
- char[] buf = s.toCharArray();
- for (int i = 0 ; i < len ; i++) {
- if (buf[i] > 255) {
- return false;
- }
- }
-
- // check the first character
- if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.') {
- return false;
- }
-
- // now look for the string that is after the float...
- Matcher m = FLOAT_PATTERN.matcher(s);
- if (m.matches()) {
- String f_str = m.group(1);
- String end = m.group(2);
-
- float f;
- try {
- f = Float.parseFloat(f_str);
- } catch (NumberFormatException e) {
- // this shouldn't happen with the regexp above.
- return false;
- }
-
- if (end.length() > 0 && end.charAt(0) != ' ') {
- // We only support dimension-type values, so try to parse the unit for dimension
- DimensionEntry dimension = parseDimension(end);
- if (dimension != null) {
- // convert the value into pixel based on the dimention type
- // This is similar to TypedValue.applyDimension()
- switch (dimension.type) {
- case COMPLEX_UNIT_PX:
- // do nothing, value is already in px
- break;
- case COMPLEX_UNIT_DIP:
- case COMPLEX_UNIT_SP: // intended fall-through since we don't
- // adjust for font size
- f *= (float)mDensity.getDpiValue() / Density.DEFAULT_DENSITY;
- break;
- case COMPLEX_UNIT_PT:
- f *= mDensity.getDpiValue() * (1.0f / 72);
- break;
- case COMPLEX_UNIT_IN:
- f *= mDensity.getDpiValue();
- break;
- case COMPLEX_UNIT_MM:
- f *= mDensity.getDpiValue() * (1.0f / 25.4f);
- break;
- }
-
- // store result (converted to int)
- sIntOut[0] = (int) (f + 0.5);
-
- return true;
- }
- }
- }
-
- return false;
- }
-
- private static DimensionEntry parseDimension(String str) {
- str = str.trim();
-
- for (DimensionEntry d : sDimensions) {
- if (d.name.equals(str)) {
- return d;
- }
- }
-
- return null;
- }
-}