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