• 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.eclipse.adt.editors.layout.gscripts;
19 
20 import com.android.ide.eclipse.adt.editors.layout.gscripts.IDragElement.IDragAttribute;
21 
22 import groovy.lang.Closure;
23 
24 
25 /**
26  * Represents a view in the XML layout being edited.
27  * Each view or layout maps to exactly one XML node, thus the name.
28  * <p/>
29  * The primordial characteristic of a node is the fully qualified View class name that
30  * it represents (a.k.a FQCN), for example "android.view.View" or "android.widget.Button".
31  * <p/>
32  * There are 2 kind of nodes:
33  * - Nodes matching a view actually rendered in the layout canvas have a valid "bounds"
34  *   rectangle that describe their position in pixels in the canvas. <br/>
35  * - Nodes created by IViewRule scripts but not yet rendered have an invalid bounds rectangle
36  *   since they only exist in the uncommitted XML model and not yet in the rendered View model.
37  */
38 public interface INode {
39 
40     /**
41      * Returns the bounds of this node.
42      * <p/>
43      * The bounds are valid when this node maps a view that is already rendered.
44      * Typically, if the node is the target of a drag'n'drop operation then you can be
45      * guaranteed that its bounds are known and thus are valid.
46      * <p/>
47      * However the bounds are invalid (e.g. not known yet) for new XML elements
48      * that have just been created, e.g. by the {@link #appendChild(String)} method.
49      *
50      * @return A non-null rectangle, in canvas coordinates.
51      */
getBounds()52     Rect getBounds();
53 
54 
55     // ---- Hierarchy handling ----
56 
57     /**
58      * Returns the root element of the view hierarchy. This may be this node if this is
59      * the root element. It can also be null when the current node is not yet or no
60      * longer attached to the hierarchy.
61      */
getRoot()62     INode getRoot();
63 
64     /**
65      * Returns the parent node of this node, corresponding to the parent view in the layout.
66      * The returned parent can be null when the node is the root element, or when the node is
67      * not yet or no longer attached to the hierarchy.
68      */
getParent()69     INode getParent();
70 
71     /**
72      * Returns the list of valid children nodes. The list can be empty but not null.
73      */
getChildren()74     INode[] getChildren();
75 
76 
77     // ---- XML Editing ---
78 
79     /**
80      * Absolutely <em>all</em> calls that are going to edit the XML must be wrapped
81      * by an editXml() call. This call creates both an undo context wrapper and an
82      * edit-XML wrapper.
83      *
84      * @param undoName The UI name that will be given to the undo action.
85      * @param closure The code to execute. The closure receives this INode itself as argument.
86      */
editXml(String undoName, final Closure closure)87     void editXml(String undoName, final Closure closure);
88 
89     // TODO define an exception that methods below will throw if editXml() is not wrapping
90     // these calls.
91 
92     /**
93      * Creates a new XML element as a child of this node's XML element.
94      * <p/>
95      * For this to work, the editor must have a descriptor for the given FQCN.
96      * <p/>
97      * This call must be done in the context of editXml().
98      *
99      * @param viewFqcn The FQCN of the element to create. The actual XML local name will
100      *  depend on whether this is an Android view or a custom project view.
101      * @return The node for the newly created element. Can be null if we failed to create it.
102      */
appendChild(String viewFqcn)103     INode appendChild(String viewFqcn);
104 
105     /**
106      * Creates a new XML element as a child of this node's XML element and inserts
107      * it at the specified position in the children list.
108      * <p/>
109      * For this to work, the editor must have a descriptor for the given FQCN.
110      * <p/>
111      * This call must be done in the context of editXml().
112      *
113      * @param viewFqcn The FQCN of the element to create. The actual XML local name will
114      *  depend on whether this is an Android view or a custom project view.
115      * @param index Index of the child to insert before. If the index is out of bounds
116      *  (less than zero or larger that current last child), appends at the end.
117      * @return The node for the newly created element. Can be null if we failed to create it.
118      */
insertChildAt(String viewFqcn, int index)119     INode insertChildAt(String viewFqcn, int index);
120 
121     /**
122      * Sets an attribute for the underlying XML element.
123      * Attributes are not written immediately -- instead the XML editor batches edits and
124      * then commits them all together at once later.
125      * <p/>
126      * Custom attributes will be created on the fly.
127      * <p/>
128      * Passing an empty value actually <em>removes</em> an attribute from the XML.
129      * <p/>
130      * This call must be done in the context of editXml().
131      *
132      * @param uri The XML namespace URI of the attribute.
133      * @param localName The XML <em>local</em> name of the attribute to set.
134      * @param value It's value. Cannot be null. An empty value <em>removes</em> the attribute.
135      * @return Whether the attribute was actually set or not.
136      */
setAttribute(String uri, String localName, String value)137     boolean setAttribute(String uri, String localName, String value);
138 
139     /**
140      * Returns a given XML attribute.
141      * <p/>
142      * This looks up an attribute in the <em>current</em> XML source, not the in-memory model.
143      * That means that if called in the context of {@link #editXml(String, Closure)}, the value
144      * returned here is not affected by {@link #setAttribute(String, String, String)} until
145      * the editXml closure is completed and the actual XML is updated.
146      *
147      * @param uri The XML name-space URI of the attribute.
148      * @param attrName The <em>local</em> name of the attribute.
149      * @return the attribute as a {@link String}, if it exists, or <code>null</code>.
150      */
getStringAttr(String uri, String attrName)151     String getStringAttr(String uri, String attrName);
152 
153     /**
154      * Returns the {@link IAttributeInfo} for a given attribute.
155      * <p/>
156      * The information is useful to determine the format of an attribute (e.g. reference, string,
157      * float, enum, flag, etc.) and in the case of enums and flags also gives the possible values.
158      * <p/>
159      * Note: in Android resources, an enum can only take one of the possible values (e.g.
160      * "visibility" can be either "visible" or "none"), whereas a flag can accept one or more
161      * value (e.g. "align" can be "center_vertical|center_horizontal".)
162      * <p/>
163      * Note that this method does not handle custom non-android attributes. It may either
164      * return null for these or it may return a synthetic "string" format attribute depending
165      * on how the attribute was loaded.
166      *
167      * @param uri The XML name-space URI of the attribute.
168      * @param attrName The <em>local</em> name of the attribute.
169      * @return the {@link IAttributeInfo} if the attribute is known, or <code>null</code>.
170      */
getAttributeInfo(String uri, String attrName)171     public IAttributeInfo getAttributeInfo(String uri, String attrName);
172 
173 
174     /**
175      * Returns the list of all attributes defined in the XML for this node.
176      * <p/>
177      * This looks up an attribute in the <em>current</em> XML source, not the in-memory model.
178      * That means that if called in the context of {@link #editXml(String, Closure)}, the value
179      * returned here is not affected by {@link #setAttribute(String, String, String)} until
180      * the editXml closure is completed and the actual XML is updated.
181      *
182      * @return A non-null possible-empty list of {@link IAttribute}.
183      */
getAttributes()184     public IAttribute[] getAttributes();
185 
186     // -----------
187 
188     /** TODO: this is a hack. Shouldn't be here but instead part of some kind of helper
189      *  given to IViewRule implementations.
190      */
debugPrintf(String msg, Object...params)191     void debugPrintf(String msg, Object...params);
192 
193     // -----------
194 
195     /**
196      * An XML attribute in an {@link INode}.
197      * <p/>
198      * The attribute is always represented by a namespace URI, a name and a value.
199      * The name cannot be empty.
200      * The namespace URI can be empty for an attribute without a namespace but is never null.
201      * The value can be empty but cannot be null.
202      */
203     public static interface IAttribute extends IDragAttribute { }
204 }
205