Home | History | Annotate | Download | only in api
      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
     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
     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
     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      */
     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
     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
    103     INode getParent();
    104 
    105     /**
    106      * Returns the list of valid children nodes. The list can be empty but not null.
    107      */
    108     @NonNull
    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      */
    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
    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
    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      */
    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      */
    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
    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
    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
    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
    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
    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