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 */ 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 */ 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 */ 69 INode getParent(); 70 71 /** 72 * Returns the list of valid children nodes. The list can be empty but not null. 73 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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