OSDN Git Service

Deprecate fill_parent and introduce match_parent. (do not merge)
[android-x86/sdk.git] / layoutopt / libs / uix / src / com / android / layoutopt / uix / groovy / LayoutAnalysisCategory.java
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.layoutopt.uix.groovy;
18
19 import com.android.layoutopt.uix.LayoutAnalysis;
20 import com.android.layoutopt.uix.xml.XmlDocumentBuilder;
21
22 import java.util.Map;
23 import java.util.List;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26
27 import groovy.lang.GString;
28 import groovy.xml.dom.DOMCategory;
29 import org.w3c.dom.Node;
30 import org.w3c.dom.NodeList;
31 import org.w3c.dom.Element;
32
33 /**
34  * Support class for Groovy rules. This class adds new Groovy capabilities
35  * to {@link com.android.layoutopt.uix.LayoutAnalysis} and {@link org.w3c.dom.Node}.
36  */
37 public class LayoutAnalysisCategory {
38     private static final String ANDROID_PADDING = "android:padding";
39     private static final String ANDROID_PADDING_LEFT = "android:paddingLeft";
40     private static final String ANDROID_PADDING_TOP = "android:paddingTop";
41     private static final String ANDROID_PADDING_RIGHT = "android:paddingRight";
42     private static final String ANDROID_PADDING_BOTTOM = "android:paddingBottom";
43     private static final String ANDROID_LAYOUT_WIDTH = "android:layout_width";
44     private static final String ANDROID_LAYOUT_HEIGHT = "android:layout_height";
45     private static final String VALUE_FILL_PARENT = "match_parent";
46     private static final String VALUE_WRAP_CONTENT = "wrap_content";
47     
48     private static final String[] sContainers = new String[] {
49             "FrameLayout", "LinearLayout", "RelativeLayout", "SlidingDrawer",
50             "AbsoluteLayout", "TableLayout", "Gallery", "GridView", "ListView",
51             "RadioGroup", "ScrollView", "HorizontalScrollView", "Spinner",
52             "ViewSwitcher", "ViewFlipper", "ViewAnimator", "ImageSwitcher",
53             "TextSwitcher", "android.gesture.GestureOverlayView", "TabHost"
54     };
55     static {
56         Arrays.sort(sContainers);
57     }
58
59     /**
60      * xmlNode.isContainer()
61      * 
62      * @return True if the specified node corresponds to a container widget.
63      */
64     public static boolean isContainer(Element element) {
65         return Arrays.binarySearch(sContainers, element.getNodeName()) >= 0;
66     }
67
68     /**
69      * xmlNode.all()
70      * 
71      * Same as xmlNode.'**' but excludes xmlNode from the results.
72      * 
73      * @return All descendants, this node excluded.
74      */
75     public static List<Node> all(Element element) {
76         NodeList list = DOMCategory.depthFirst(element);
77         int count = list.getLength();
78         List<Node> nodes = new ArrayList<Node>(count - 1);
79         for (int i = 1; i < count; i++) {
80             nodes.add(list.item(i));
81         }
82         return nodes;
83     }
84
85     /**
86      * Returns the start line of this node.
87      *
88      * @return The start line or -1 if the line is unknown.
89      */
90     public static int getStartLine(Node node) {
91         final Object data = node == null ? null :
92                 node.getUserData(XmlDocumentBuilder.NODE_START_LINE);
93         return data == null ? -1 : (Integer) data;
94     }
95
96     /**
97      * Returns the end line of this node.
98      *
99      * @return The end line or -1 if the line is unknown.
100      */
101     public static int getEndLine(Node node) {
102         final Object data = node == null ? null :
103                 node.getUserData(XmlDocumentBuilder.NODE_END_LINE);
104         return data == null ? -1 : (Integer) data;
105     }
106
107     /**
108      * xmlNode.hasPadding()
109      * 
110      * @return True if the node has one ore more padding attributes.
111      */
112     public static boolean hasPadding(Element element) {
113         return element.getAttribute(ANDROID_PADDING).length() > 0 ||
114                 element.getAttribute(ANDROID_PADDING_LEFT).length() > 0 ||
115                 element.getAttribute(ANDROID_PADDING_TOP).length() > 0 ||
116                 element.getAttribute(ANDROID_PADDING_BOTTOM).length() > 0 ||
117                 element.getAttribute(ANDROID_PADDING_RIGHT).length() > 0;
118     }
119
120     /**
121      * Returns whether this node's width is match_parent.
122      */
123     public static boolean isWidthFillParent(Element element) {
124         return element.getAttribute(ANDROID_LAYOUT_WIDTH).equals(VALUE_FILL_PARENT);
125     }
126
127     /**
128      * Returns whether this node's width is wrap_content.
129      */
130     public static boolean isWidthWrapContent(Element element) {
131         return element.getAttribute(ANDROID_LAYOUT_WIDTH).equals(VALUE_WRAP_CONTENT);
132     }
133
134     /**
135      * Returns whether this node's height is match_parent.
136      */
137     public static boolean isHeightFillParent(Element element) {
138         return element.getAttribute(ANDROID_LAYOUT_HEIGHT).equals(VALUE_FILL_PARENT);
139     }
140
141     /**
142      * Returns whether this node's height is wrap_content.
143      */
144     public static boolean isHeightWrapContent(Element element) {
145         return element.getAttribute(ANDROID_LAYOUT_HEIGHT).equals(VALUE_WRAP_CONTENT);
146     }
147
148     /**
149      * xmlNode.isRoot()
150      * 
151      * @return True if xmlNode is the root of the document, false otherwise
152      */
153     public static boolean isRoot(Node node) {
154         return node.getOwnerDocument().getDocumentElement() == node;
155     }
156
157     /**
158      * xmlNode.is("tagName")
159      * 
160      * @return True if xmlNode.getNodeName().equals(name), false otherwise.
161      */
162     public static boolean is(Node node, String name) {
163         return node.getNodeName().equals(name);
164     }
165
166     /**
167      * xmlNode.depth()
168      * 
169      * @return The maximum depth of the node.
170      */
171     public static int depth(Node node) {
172         int maxDepth = 0;
173         NodeList list = node.getChildNodes();
174         int count = list.getLength();
175
176         for (int i = 0; i < count; i++) {
177             maxDepth = Math.max(maxDepth, depth(list.item(i)));
178         }
179
180         return maxDepth + 1;
181     }
182
183     /**
184      * analysis << "The issue"
185      * 
186      * @return The analysis itself to chain calls.
187      */
188     public static LayoutAnalysis leftShift(LayoutAnalysis analysis, GString description) {
189         analysis.addIssue(description.toString());
190         return analysis;
191     }
192
193     /**
194      * analysis << "The issue"
195      * 
196      * @return The analysis itself to chain calls.
197      */
198     public static LayoutAnalysis leftShift(LayoutAnalysis analysis, String description) {
199         analysis.addIssue(description);
200         return analysis;
201     }
202
203     /**
204      * analysis << [node: node, description: "The issue"]
205      * 
206      * @return The analysis itself to chain calls.
207      */
208     public static LayoutAnalysis leftShift(LayoutAnalysis analysis, Map issue) {
209         analysis.addIssue((Node) issue.get("node"), issue.get("description").toString());
210         return analysis;
211     }
212 }