aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ExplodedRenderingHelper.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/ExplodedRenderingHelper.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ExplodedRenderingHelper.java421
1 files changed, 0 insertions, 421 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ExplodedRenderingHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ExplodedRenderingHelper.java
deleted file mode 100644
index 25fa3e991..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ExplodedRenderingHelper.java
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright (C) 2009 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 com.android.SdkConstants;
-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;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.sdklib.IAndroidTarget;
-
-import org.eclipse.core.resources.IProject;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-/**
- * This class computes the new screen size in "exploded rendering" mode.
- * It goes through the whole layout tree and figures out how many embedded layouts will have
- * extra padding and compute how that will affect the screen size.
- *
- * TODO
- * - find a better class name :)
- * - move the logic for each layout to the layout rule classes?
- * - support custom classes (by querying JDT for its super class and reverting to its behavior)
- */
-public final class ExplodedRenderingHelper {
- /** value of the padding in pixel.
- * TODO: make a preference?
- */
- public final static int PADDING_VALUE = 10;
-
- private final int[] mPadding = new int[] { 0, 0 };
- private Set<String> mLayoutNames;
-
- /**
- * Computes the padding. access the result through {@link #getWidthPadding()} and
- * {@link #getHeightPadding()}.
- * @param root the root node (ie the top layout).
- * @param iProject the project to which the layout belong.
- */
- public ExplodedRenderingHelper(Node root, IProject iProject) {
- // get the layout descriptors to get the name of all the layout classes.
- IAndroidTarget target = Sdk.getCurrent().getTarget(iProject);
- AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
- LayoutDescriptors descriptors = data.getLayoutDescriptors();
-
- mLayoutNames = new HashSet<String>();
- List<ViewElementDescriptor> layoutDescriptors = descriptors.getLayoutDescriptors();
- for (ViewElementDescriptor desc : layoutDescriptors) {
- mLayoutNames.add(desc.getXmlLocalName());
- }
-
- computePadding(root, mPadding);
- }
-
- /**
- * (Unit tests only)
- * Computes the padding. access the result through {@link #getWidthPadding()} and
- * {@link #getHeightPadding()}.
- * @param root the root node (ie the top layout).
- * @param layoutNames the list of layout classes
- */
- public ExplodedRenderingHelper(Node root, Set<String> layoutNames) {
- mLayoutNames = layoutNames;
-
- computePadding(root, mPadding);
- }
-
- /**
- * Returns the number of extra padding in the X axis. This doesn't return a number of pixel
- * or dip, but how many paddings are pushing the screen dimension out.
- */
- public int getWidthPadding() {
- return mPadding[0];
- }
-
- /**
- * Returns the number of extra padding in the Y axis. This doesn't return a number of pixel
- * or dip, but how many paddings are pushing the screen dimension out.
- */
- public int getHeightPadding() {
- return mPadding[1];
- }
-
- /**
- * Computes the number of padding for a given view, and fills the given array of int.
- * <p/>index 0 is X axis, index 1 is Y axis
- * @param view the view to compute
- * @param padding the result padding (index 0 is X axis, index 1 is Y axis)
- */
- private void computePadding(Node view, int[] padding) {
- String localName = view.getLocalName();
-
- // first compute for each children
- NodeList children = view.getChildNodes();
- int count = children.getLength();
- if (count > 0) {
- // compute the padding for all the children.
- Map<Node, int[]> childrenPadding = new HashMap<Node, int[]>(count);
- for (int i = 0 ; i < count ; i++) {
- Node child = children.item(i);
- short type = child.getNodeType();
- if (type == Node.ELEMENT_NODE) { // ignore TEXT/CDATA nodes.
- int[] p = new int[] { 0, 0 };
- childrenPadding.put(child, p);
- computePadding(child, p);
- }
- }
-
- // since the non ELEMENT_NODE children were filtered out, count must be updated.
- count = childrenPadding.size();
-
- // now combine/compare based on the parent.
- if (count == 1) {
- int[] p = childrenPadding.get(childrenPadding.keySet().iterator().next());
- padding[0] = p[0];
- padding[1] = p[1];
- } else {
- if ("LinearLayout".equals(localName)) { //$NON-NLS-1$
- String orientation = getAttribute(view, "orientation", null); //$NON-NLS-1$
-
- // default value is horizontal
- boolean horizontal = orientation == null ||
- "horizontal".equals("vertical"); //$NON-NLS-1$ //$NON-NLS-2$
- combineLinearLayout(childrenPadding.values(), padding, horizontal);
- } else if ("TableLayout".equals(localName)) { //$NON-NLS-1$
- combineLinearLayout(childrenPadding.values(), padding, false /*horizontal*/);
- } else if ("TableRow".equals(localName)) { //$NON-NLS-1$
- combineLinearLayout(childrenPadding.values(), padding, true /*true*/);
- // TODO: properly support Relative Layouts.
-// } else if ("RelativeLayout".equals(localName)) { //$NON-NLS-1$
-// combineRelativeLayout(childrenPadding, padding);
- } else {
- // unknown layout. For now, let's consider it's better to add the children
- // margins in both dimensions than not at all.
- for (int[] p : childrenPadding.values()) {
- padding[0] += p[0];
- padding[1] += p[1];
- }
- }
- }
- }
-
- // if the view itself is a layout, add its padding
- if (mLayoutNames.contains(localName)) {
- padding[0]++;
- padding[1]++;
- }
- }
-
- /**
- * Combines the padding of the children of a linear layout.
- * <p/>For this layout, the padding of the children are added in the direction of
- * the layout, while the max is taken for the other direction.
- * @param paddings the list of the padding for the children.
- * @param resultPadding the result padding array to fill.
- * @param horizontal whether this layout is horizontal (<code>true</code>) or vertical
- * (<code>false</code>)
- */
- private void combineLinearLayout(Collection<int[]> paddings, int[] resultPadding,
- boolean horizontal) {
- // The way the children are combined will depend on the direction.
- // For instance in a vertical layout, we add the y padding as they all add to the length
- // of the needed canvas, while we take the biggest x padding needed by the children
-
- // the axis in which we take the sum of the padding of the children
- int sumIndex = horizontal ? 0 : 1;
- // the axis in which we take the max of the padding of the children
- int maxIndex = horizontal ? 1 : 0;
-
- int max = -1;
- for (int[] p : paddings) {
- resultPadding[sumIndex] += p[sumIndex];
- if (max == -1 || max < p[maxIndex]) {
- max = p[maxIndex];
- }
- }
- resultPadding[maxIndex] = max;
- }
-
- /**
- * Combine the padding of children of a relative layout.
- * @param childrenPadding a map of the children. This is guaranteed that the node object
- * are of type ELEMENT_NODE
- * @param padding
- *
- * TODO: Not used yet. Still need (lots of) work.
- */
- private void combineRelativeLayout(Map<Node, int[]> childrenPadding, int[] padding) {
- /*
- * Combines the children of the layout.
- * The way this works: for each children, for each direction, look for all the chidrens
- * connected and compute the combined margin in that direction.
- *
- * There's a chance the returned value will be too much. this is due to the layout sometimes
- * dropping views which will not be dropped here. It's ok, as it's better to have too
- * much than not enough.
- * We could fix this by matching those UiElementNode with their bounds as returned
- * by the rendering (ie if bounds is 0/0 in h/w, then ignore the child)
- */
-
- // list of the UiElementNode
- Set<Node> nodeSet = childrenPadding.keySet();
- // map of Id -> node
- Map<String, Node> idNodeMap = computeIdNodeMap(nodeSet);
-
- for (Entry<Node, int[]> entry : childrenPadding.entrySet()) {
- Node node = entry.getKey();
-
- // first horizontal, to the left.
- int[] leftResult = getBiggestMarginInDirection(node, 0 /*horizontal*/,
- "layout_toRightOf", "layout_toLeftOf", //$NON-NLS-1$ //$NON-NLS-2$
- childrenPadding, nodeSet, idNodeMap,
- false /*includeThisPadding*/);
-
- // then to the right
- int[] rightResult = getBiggestMarginInDirection(node, 0 /*horizontal*/,
- "layout_toLeftOf", "layout_toRightOf", //$NON-NLS-1$ //$NON-NLS-2$
- childrenPadding, nodeSet, idNodeMap,
- false /*includeThisPadding*/);
-
- // compute total horizontal margins
- int[] thisPadding = childrenPadding.get(node);
- int combinedMargin =
- (thisPadding != null ? thisPadding[0] : 0) +
- (leftResult != null ? leftResult[0] : 0) +
- (rightResult != null ? rightResult[0] : 0);
- if (combinedMargin > padding[0]) {
- padding[0] = combinedMargin;
- }
-
- // first vertical, above.
- int[] topResult = getBiggestMarginInDirection(node, 1 /*horizontal*/,
- "layout_below", "layout_above", //$NON-NLS-1$ //$NON-NLS-2$
- childrenPadding, nodeSet, idNodeMap,
- false /*includeThisPadding*/);
-
- // then below
- int[] bottomResult = getBiggestMarginInDirection(node, 1 /*horizontal*/,
- "layout_above", "layout_below", //$NON-NLS-1$ //$NON-NLS-2$
- childrenPadding, nodeSet, idNodeMap,
- false /*includeThisPadding*/);
-
- // compute total horizontal margins
- combinedMargin =
- (thisPadding != null ? thisPadding[1] : 0) +
- (topResult != null ? topResult[1] : 0) +
- (bottomResult != null ? bottomResult[1] : 0);
- if (combinedMargin > padding[1]) {
- padding[1] = combinedMargin;
- }
- }
- }
-
- /**
- * Computes the biggest margin in a given direction.
- *
- * TODO: Not used yet. Still need (lots of) work.
- */
- private int[] getBiggestMarginInDirection(Node node, int resIndex, String relativeTo,
- String inverseRelation, Map<Node, int[]> childrenPadding,
- Set<Node> nodeSet, Map<String, Node> idNodeMap,
- boolean includeThisPadding) {
- NamedNodeMap attributes = node.getAttributes();
-
- String viewId = getAttribute(node, "id", attributes); //$NON-NLS-1$
-
- // first get the item this one is positioned relative to.
- String toLeftOfRef = getAttribute(node, relativeTo, attributes);
- Node toLeftOf = null;
- if (toLeftOfRef != null) {
- toLeftOf = idNodeMap.get(cleanUpIdReference(toLeftOfRef));
- }
-
- ArrayList<Node> list = null;
- if (viewId != null) {
- // now to the left for items being placed to the left of this one.
- list = getMatchingNode(nodeSet, cleanUpIdReference(viewId), inverseRelation);
- }
-
- // now process each children in the same direction.
- if (toLeftOf != null) {
- if (list == null) {
- list = new ArrayList<Node>();
- }
-
- if (list.indexOf(toLeftOf) == -1) {
- list.add(toLeftOf);
- }
- }
-
- int[] thisPadding = childrenPadding.get(node);
-
- if (list != null) {
- // since there's a combination to do, we'll return a new result object
- int[] result = null;
- for (Node nodeOnLeft : list) {
- int[] tempRes = getBiggestMarginInDirection(nodeOnLeft, resIndex, relativeTo,
- inverseRelation, childrenPadding, nodeSet, idNodeMap, true);
- if (tempRes != null && (result == null || result[resIndex] < tempRes[resIndex])) {
- result = tempRes;
- }
- }
-
- // return the combined padding
- if (includeThisPadding == false || thisPadding[resIndex] == 0) {
- // just return the one we got since this object adds no padding (or doesn't
- // need to be comibined)
- return result;
- } else if (result != null) { // if result is null, the main return below is used.
- // add the result we got with the padding from the current node
- int[] realRes = new int [2];
- realRes[resIndex] = thisPadding[resIndex] + result[resIndex];
- return realRes;
- }
- }
-
- // if we reach this, there were no other views to the left of this one, so just return
- // the view padding.
- return includeThisPadding ? thisPadding : null;
- }
-
- /**
- * Computes and returns a map of (id, node) for each node of a given {@link Set}.
- * <p/>
- * Nodes with no id are ignored and not put in the map.
- * @param nodes the nodes to fill the map with.
- * @return a newly allocated, non-null, map of (id, node)
- */
- private Map<String, Node> computeIdNodeMap(Set<Node> nodes) {
- Map<String, Node> map = new HashMap<String, Node>();
- for (Node node : nodes) {
- String viewId = getAttribute(node, "id", null); //$NON-NLS-1$
- if (viewId != null) {
- map.put(cleanUpIdReference(viewId), node);
- }
- }
- return map;
- }
-
- /**
- * Cleans up a reference to an ID to return the ID itself only.
- * @param reference the reference to "clean up".
- * @return the id string only.
- */
- private String cleanUpIdReference(String reference) {
- // format is @id/foo or @+id/foo or @android:id/foo, or something similar.
- int slash = reference.indexOf('/');
- return reference.substring(slash);
- }
-
- /**
- * Returns a list of nodes for which a given attribute contains a reference to a given ID.
- *
- * @param nodes the list of nodes to search through
- * @param resId the requested ID
- * @param attribute the name of the attribute to test.
- * @return a newly allocated, non-null, list of nodes. Could be empty.
- */
- private ArrayList<Node> getMatchingNode(Set<Node> nodes, String resId,
- String attribute) {
- ArrayList<Node> list = new ArrayList<Node>();
-
- for (Node node : nodes) {
- String value = getAttribute(node, attribute, null);
- if (value != null) {
- value = cleanUpIdReference(value);
- if (value.equals(resId)) {
- list.add(node);
- }
- }
- }
-
- return list;
- }
-
- /**
- * Returns an attribute for a given node.
- * @param node the node to query
- * @param name the name of an attribute
- * @param attributes the option {@link NamedNodeMap} object to use to read the attributes from.
- */
- private static String getAttribute(Node node, String name, NamedNodeMap attributes) {
- if (attributes == null) {
- attributes = node.getAttributes();
- }
-
- if (attributes != null) {
- Node attribute = attributes.getNamedItemNS(SdkConstants.NS_RESOURCES, name);
- if (attribute != null) {
- return attribute.getNodeValue();
- }
- }
-
- return null;
- }
-}