• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
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 
18 package com.android.ide.common.api;
19 
20 import com.android.annotations.NonNull;
21 import com.android.annotations.Nullable;
22 import com.android.ide.common.api.IDragElement.IDragAttribute;
23 import com.google.common.annotations.Beta;
24 
25 import java.util.List;
26 
27 
28 /**
29  * Represents a view in the XML layout being edited.
30  * Each view or layout maps to exactly one XML node, thus the name.
31  * <p/>
32  * The primordial characteristic of a node is the fully qualified View class name that
33  * it represents (a.k.a FQCN), for example "android.view.View" or "android.widget.Button".
34  * <p/>
35  * There are 2 kind of nodes:
36  * - Nodes matching a view actually rendered in the layout canvas have a valid "bounds"
37  *   rectangle that describe their position in pixels in the canvas. <br/>
38  * - Nodes created by IViewRule scripts but not yet rendered have an invalid bounds rectangle
39  *   since they only exist in the uncommitted XML model and not yet in the rendered View model.
40  * <p>
41  * <b>NOTE: This is not a public or final API; if you rely on this be prepared
42  * to adjust your code for the next tools release.</b>
43  * </p>
44  */
45 @Beta
46 public interface INode {
47 
48     /**
49      * Returns the FQCN of the view class represented by this node.
50      */
51     @NonNull
getFqcn()52     String getFqcn();
53 
54     /**
55      * Returns the bounds of this node.
56      * <p/>
57      * The bounds are valid when this node maps a view that is already rendered.
58      * Typically, if the node is the target of a drag'n'drop operation then you can be
59      * guaranteed that its bounds are known and thus are valid.
60      * <p/>
61      * However the bounds are invalid (e.g. not known yet) for new XML elements
62      * that have just been created, e.g. by the {@link #appendChild(String)} method.
63      *
64      * @return A non-null rectangle, in canvas coordinates.
65      */
66     @NonNull
getBounds()67     Rect getBounds();
68 
69     /**
70      * Returns the margins for this node.
71      *
72      * @return the margins for this node, never null
73      */
74     @NonNull
getMargins()75     Margins getMargins();
76 
77     /**
78      * Returns the baseline of this node, or -1 if it has no baseline.
79      * The baseline is the distance from the top down to the baseline.
80      *
81      * @return the baseline, or -1 if not applicable
82      */
getBaseline()83     int getBaseline();
84 
85     // ---- Hierarchy handling ----
86 
87     /**
88      * Returns the root element of the view hierarchy.
89      * <p/>
90      * When a node is not attached to a hierarchy, it is its own root node.
91      * This may return null if the {@link INode} was not created using a correct UiNode,
92      * which is unlikely.
93      */
94     @Nullable
getRoot()95     INode getRoot();
96 
97     /**
98      * Returns the parent node of this node, corresponding to the parent view in the layout.
99      * The returned parent can be null when the node is the root element, or when the node is
100      * not yet or no longer attached to the hierarchy.
101      */
102     @Nullable
getParent()103     INode getParent();
104 
105     /**
106      * Returns the list of valid children nodes. The list can be empty but not null.
107      */
108     @NonNull
getChildren()109     INode[] getChildren();
110 
111 
112     // ---- XML Editing ---
113 
114     /**
115      * Absolutely <em>all</em> calls that are going to edit the XML must be wrapped
116      * by an editXml() call. This call creates both an undo context wrapper and an
117      * edit-XML wrapper.
118      *
119      * @param undoName The UI name that will be given to the undo action.
120      * @param callback The code to execute.
121      */
editXml(@onNull String undoName, @NonNull INodeHandler callback)122     void editXml(@NonNull String undoName, @NonNull INodeHandler callback);
123 
124     // TODO define an exception that methods below will throw if editXml() is not wrapping
125     // these calls.
126 
127     /**
128      * Creates a new XML element as a child of this node's XML element.
129      * <p/>
130      * For this to work, the editor must have a descriptor for the given FQCN.
131      * <p/>
132      * This call must be done in the context of editXml().
133      *
134      * @param viewFqcn The FQCN of the element to create. The actual XML local name will
135      *  depend on whether this is an Android view or a custom project view.
136      * @return The node for the newly created element. Can be null if we failed to create it.
137      */
138     @NonNull
appendChild(@onNull String viewFqcn)139     INode appendChild(@NonNull String viewFqcn);
140 
141     /**
142      * Creates a new XML element as a child of this node's XML element and inserts
143      * it at the specified position in the children list.
144      * <p/>
145      * For this to work, the editor must have a descriptor for the given FQCN.
146      * <p/>
147      * This call must be done in the context of editXml().
148      *
149      * @param viewFqcn The FQCN of the element to create. The actual XML local name will
150      *  depend on whether this is an Android view or a custom project view.
151      * @param index Index of the child to insert before. If the index is out of bounds
152      *  (less than zero or larger that current last child), appends at the end.
153      * @return The node for the newly created element. Can be null if we failed to create it.
154      */
155     @NonNull
insertChildAt(@onNull String viewFqcn, int index)156     INode insertChildAt(@NonNull String viewFqcn, int index);
157 
158     /**
159      * Removes the given XML element child from this node's list of children.
160      * <p/>
161      * This call must be done in the context of editXml().
162      *
163      * @param node The child to be deleted.
164      */
removeChild(@onNull INode node)165     void removeChild(@NonNull INode node);
166 
167     /**
168      * Sets an attribute for the underlying XML element.
169      * Attributes are not written immediately -- instead the XML editor batches edits and
170      * then commits them all together at once later.
171      * <p/>
172      * Custom attributes will be created on the fly.
173      * <p/>
174      * Passing an empty value actually <em>removes</em> an attribute from the XML.
175      * <p/>
176      * This call must be done in the context of editXml().
177      *
178      * @param uri The XML namespace URI of the attribute.
179      * @param localName The XML <em>local</em> name of the attribute to set.
180      * @param value It's value. Cannot be null. An empty value <em>removes</em> the attribute.
181      * @return Whether the attribute was actually set or not.
182      */
setAttribute(@ullable String uri, @NonNull String localName, @Nullable String value)183     boolean setAttribute(@Nullable String uri, @NonNull String localName, @Nullable String value);
184 
185     /**
186      * Returns a given XML attribute.
187      * <p/>
188      * This looks up an attribute in the <em>current</em> XML source, not the in-memory model.
189      * That means that if called in the context of {@link #editXml(String, INodeHandler)}, the value
190      * returned here is not affected by {@link #setAttribute(String, String, String)} until
191      * the editXml closure is completed and the actual XML is updated.
192      *
193      * @param uri The XML name-space URI of the attribute.
194      * @param attrName The <em>local</em> name of the attribute.
195      * @return the attribute as a {@link String}, if it exists, or <code>null</code>.
196      */
197     @Nullable
getStringAttr(@ullable String uri, @NonNull String attrName)198     String getStringAttr(@Nullable String uri, @NonNull String attrName);
199 
200     /**
201      * Returns the {@link IAttributeInfo} for a given attribute.
202      * <p/>
203      * The information is useful to determine the format of an attribute (e.g. reference, string,
204      * float, enum, flag, etc.) and in the case of enums and flags also gives the possible values.
205      * <p/>
206      * Note: in Android resources, an enum can only take one of the possible values (e.g.
207      * "visibility" can be either "visible" or "none"), whereas a flag can accept one or more
208      * value (e.g. "align" can be "center_vertical|center_horizontal".)
209      * <p/>
210      * Note that this method does not handle custom non-android attributes. It may either
211      * return null for these or it may return a synthetic "string" format attribute depending
212      * on how the attribute was loaded.
213      *
214      * @param uri The XML name-space URI of the attribute.
215      * @param attrName The <em>local</em> name of the attribute.
216      * @return the {@link IAttributeInfo} if the attribute is known, or <code>null</code>.
217      */
218     @Nullable
getAttributeInfo(@ullable String uri, @NonNull String attrName)219     public IAttributeInfo getAttributeInfo(@Nullable String uri, @NonNull String attrName);
220 
221     /**
222      * Returns the list of all attributes declared by this node's descriptor.
223      * <p/>
224      * This returns a fixed list of all attributes known to the view or layout descriptor.
225      * This list does not depend on whether the attributes are actually used in the
226      * XML for this node.
227      * <p/>
228      * Note that for views, the list of attributes also includes the layout attributes
229      * inherited from the parent view. This means callers must not cache this list based
230      * solely on the type of the node, as its attribute list changes depending on the place
231      * of the view in the view hierarchy.
232      * <p/>
233      * If you want attributes actually written in the XML and their values, please use
234      * {@link #getStringAttr(String, String)} or {@link #getLiveAttributes()} instead.
235      *
236      * @return A non-null possibly-empty list of {@link IAttributeInfo}.
237      */
238     @NonNull
getDeclaredAttributes()239     public IAttributeInfo[] getDeclaredAttributes();
240 
241     /**
242      * Returns the list of classes (fully qualified class names) that are
243      * contributing properties to the {@link #getDeclaredAttributes()} attribute
244      * list, in order from most specific to least specific (in other words,
245      * android.view.View will be last in the list.) This is usually the same as
246      * the super class chain of a view, but it skips any views that do not
247      * contribute attributes.
248      *
249      * @return a list of views classes that contribute attributes to this node,
250      *         which is never null because at least android.view.View will
251      *         contribute attributes.
252      */
253     @NonNull
getAttributeSources()254     public List<String> getAttributeSources();
255 
256     /**
257      * Returns the list of all attributes defined in the XML for this node.
258      * <p/>
259      * This looks up an attribute in the <em>current</em> XML source, not the in-memory model.
260      * That means that if called in the context of {@link #editXml(String, INodeHandler)}, the value
261      * returned here is not affected by {@link #setAttribute(String, String, String)} until
262      * the editXml closure is completed and the actual XML is updated.
263      * <p/>
264      * If you want a list of all possible attributes, whether used in the XML or not by
265      * this node, please see {@link #getDeclaredAttributes()} instead.
266      *
267      * @return A non-null possibly-empty list of {@link IAttribute}.
268      */
269     @NonNull
getLiveAttributes()270     public IAttribute[] getLiveAttributes();
271 
272     // -----------
273 
274     /**
275      * An XML attribute in an {@link INode} with a namespace URI, a name and its current value.
276      * <p/>
277      * The name cannot be empty.
278      * The namespace URI can be empty for an attribute without a namespace but is never null.
279      * The value can be empty but cannot be null.
280      */
281     public static interface IAttribute extends IDragAttribute { }
282 }
283