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