Home | History | Annotate | Download | only in descriptors
      1 /*
      2  * Copyright (C) 2008 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 package com.android.ide.eclipse.adt.internal.editors.layout.descriptors;
     18 
     19 import static com.android.ide.common.layout.LayoutConstants.ANDROID_VIEW_PKG;
     20 import static com.android.ide.common.layout.LayoutConstants.ANDROID_WEBKIT_PKG;
     21 import static com.android.ide.common.layout.LayoutConstants.ANDROID_WIDGET_PREFIX;
     22 
     23 import com.android.ide.common.resources.platform.AttributeInfo;
     24 import com.android.ide.eclipse.adt.AdtPlugin;
     25 import com.android.ide.eclipse.adt.internal.editors.IconFactory;
     26 import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
     27 import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
     28 import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
     29 import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
     30 
     31 import org.eclipse.swt.graphics.Image;
     32 
     33 import java.util.Collections;
     34 import java.util.List;
     35 
     36 /**
     37  * {@link ViewElementDescriptor} describes the properties expected for a given XML element node
     38  * representing a class in an XML Layout file.
     39  * <p/>
     40  * These descriptors describe Android views XML elements.
     41  * <p/>
     42  * The base class {@link ElementDescriptor} has a notion of "children", that is an XML element
     43  * can produce another set of XML elements. Because of the flat nature of Android's layout
     44  * XML files all possible views are children of the document and of themselves (that is any
     45  * view group can contain any other view). This is an implied contract of this class that is
     46  * enforces at construction by {@link LayoutDescriptors}. Note that by construction any code
     47  * that deals with the children hierarchy must also deal with potential infinite loops since views
     48  * <em>will</em> reference themselves (e.g. a ViewGroup can contain a ViewGroup).
     49  * <p/>
     50  * Since Views are also Java classes, they derive from each other. Here this is represented
     51  * as the "super class", which denotes the fact that a given View java class derives from
     52  * another class. These properties are also set at construction by {@link LayoutDescriptors}.
     53  * The super class hierarchy is very different from the descriptor's children hierarchy: the
     54  * later represents Java inheritance, the former represents an XML nesting capability.
     55  *
     56  * @see ElementDescriptor
     57  */
     58 public class ViewElementDescriptor extends ElementDescriptor {
     59 
     60     /** The full class name (FQCN) of this view. */
     61     private final String mFullClassName;
     62 
     63     /** The list of layout attributes. Can be empty but not null. */
     64     private AttributeDescriptor[] mLayoutAttributes;
     65 
     66     /** The super-class descriptor. Can be null. */
     67     private ViewElementDescriptor mSuperClassDesc;
     68 
     69     /** List of attribute sources, classes that contribute attributes to {@link #mAttributes} */
     70     private List<String> mAttributeSources;
     71 
     72     /**
     73      * Constructs a new {@link ViewElementDescriptor} based on its XML name, UI name,
     74      * the canonical name of the class it represents, its tooltip, its SDK url, its attributes list,
     75      * its children list and its mandatory flag.
     76      *
     77      * @param xml_name The XML element node name. Case sensitive.
     78      * @param ui_name The XML element name for the user interface, typically capitalized.
     79      * @param fullClassName The fully qualified class name the {@link ViewElementDescriptor} is
     80      *          representing.
     81      * @param tooltip An optional tooltip. Can be null or empty.
     82      * @param sdk_url An optional SKD URL. Can be null or empty.
     83      * @param attributes The list of allowed attributes. Can be null or empty.
     84      * @param layoutAttributes The list of layout attributes. Can be null or empty.
     85      * @param children The list of allowed children. Can be null or empty.
     86      * @param mandatory Whether this node must always exist (even for empty models). A mandatory
     87      *  UI node is never deleted and it may lack an actual XML node attached. A non-mandatory
     88      *  UI node MUST have an XML node attached and it will cease to exist when the XML node
     89      *  ceases to exist.
     90      */
     91     public ViewElementDescriptor(String xml_name, String ui_name,
     92             String fullClassName,
     93             String tooltip, String sdk_url,
     94             AttributeDescriptor[] attributes, AttributeDescriptor[] layoutAttributes,
     95             ElementDescriptor[] children, boolean mandatory) {
     96         super(xml_name, ui_name, tooltip, sdk_url, attributes, children, mandatory);
     97         mFullClassName = fullClassName;
     98         mLayoutAttributes = layoutAttributes != null ? layoutAttributes : new AttributeDescriptor[0];
     99     }
    100 
    101     /**
    102      * Constructs a new {@link ElementDescriptor} based on its XML name and on the canonical
    103      * name of the class it represents.
    104      * The UI name is build by capitalizing the XML name.
    105      * The UI nodes will be non-mandatory.
    106      *
    107      * @param xml_name The XML element node name. Case sensitive.
    108      * @param fullClassName The fully qualified class name the {@link ViewElementDescriptor} is
    109      * representing.
    110      */
    111     public ViewElementDescriptor(String xml_name, String fullClassName) {
    112         super(xml_name);
    113         mFullClassName = fullClassName;
    114         mLayoutAttributes = null;
    115     }
    116 
    117     /**
    118      * Returns the fully qualified name of the View class represented by this element descriptor
    119      * e.g. "android.view.View".
    120      *
    121      * @return the fully qualified class name, never null
    122      */
    123     public String getFullClassName() {
    124         return mFullClassName;
    125     }
    126 
    127     /** Returns the list of layout attributes. Can be empty but not null.
    128      *
    129      * @return the list of layout attributes, never null
    130      */
    131     public AttributeDescriptor[] getLayoutAttributes() {
    132         return mLayoutAttributes;
    133     }
    134 
    135     /**
    136      * Sets the list of layout attribute attributes.
    137      *
    138      * @param attributes the new layout attributes, not null
    139      */
    140     public void setLayoutAttributes(AttributeDescriptor[] attributes) {
    141         assert attributes != null;
    142         mLayoutAttributes = attributes;
    143     }
    144 
    145     /**
    146      * Returns a new {@link UiViewElementNode} linked to this descriptor.
    147      */
    148     @Override
    149     public UiElementNode createUiNode() {
    150         return new UiViewElementNode(this);
    151     }
    152 
    153     /**
    154      * Returns the {@link ViewElementDescriptor} of the super-class of this View descriptor
    155      * that matches the java View hierarchy. Can be null.
    156      *
    157      * @return the super class' descriptor or null
    158      */
    159     public ViewElementDescriptor getSuperClassDesc() {
    160         return mSuperClassDesc;
    161     }
    162 
    163     /**
    164      * Sets the {@link ViewElementDescriptor} of the super-class of this View descriptor
    165      * that matches the java View hierarchy. Can be null.
    166      *
    167      * @param superClassDesc the descriptor for the super class, or null
    168      */
    169     public void setSuperClass(ViewElementDescriptor superClassDesc) {
    170         mSuperClassDesc = superClassDesc;
    171     }
    172 
    173     /**
    174      * Returns an optional icon for the element.
    175      * <p/>
    176      * By default this tries to return an icon based on the XML name of the element.
    177      * If this fails, it tries to return the default element icon as defined in the
    178      * plugin. If all fails, it returns null.
    179      *
    180      * @return An icon for this element or null.
    181      */
    182     @Override
    183     public Image getGenericIcon() {
    184         IconFactory factory = IconFactory.getInstance();
    185         String name = mXmlName;
    186         if (name.indexOf('.') != -1) {
    187             // If the user uses a fully qualified name, such as
    188             // "android.gesture.GestureOverlayView" in their XML, we need to look up
    189             // only by basename
    190             name = name.substring(name.lastIndexOf('.') + 1);
    191         }
    192 
    193         Image icon = factory.getIcon(name);
    194         if (icon == null) {
    195             icon = AdtPlugin.getAndroidLogo();
    196         }
    197 
    198         return icon;
    199     }
    200 
    201     /**
    202      * Returns the list of attribute sources for the attributes provided by this
    203      * descriptor. An attribute source is the fully qualified class name of the
    204      * defining class for some of the properties. The specific attribute source
    205      * of a given {@link AttributeInfo} can be found by calling
    206      * {@link AttributeInfo#getDefinedBy()}.
    207      * <p>
    208      * The attribute sources are ordered from class to super class.
    209      * <p>
    210      * The list may <b>not</b> be modified by clients.
    211      *
    212      * @return a non null list of attribute sources for this view
    213      */
    214     public List<String> getAttributeSources() {
    215         return mAttributeSources != null ? mAttributeSources : Collections.<String>emptyList();
    216     }
    217 
    218     /**
    219      * Sets the attribute sources for this view. See {@link #getAttributes()}
    220      * for details.
    221      *
    222      * @param attributeSources a non null list of attribute sources for this
    223      *            view descriptor
    224      * @see #getAttributeSources()
    225      */
    226     public void setAttributeSources(List<String> attributeSources) {
    227         mAttributeSources = attributeSources;
    228     }
    229 
    230     /**
    231      * Returns true if views with the given fully qualified class name need to include
    232      * their package in the layout XML tag
    233      *
    234      * @param fqcn the fully qualified class name, such as android.widget.Button
    235      * @return true if the full package path should be included in the layout XML element
    236      *         tag
    237      */
    238     public static boolean viewNeedsPackage(String fqcn) {
    239         return !(fqcn.startsWith(ANDROID_WIDGET_PREFIX)
    240               || fqcn.startsWith(ANDROID_VIEW_PKG)
    241               || fqcn.startsWith(ANDROID_WEBKIT_PKG));
    242     }
    243 }
    244