1 /* 2 * Copyright (C) 2007 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.descriptors; 18 19 import com.android.annotations.NonNull; 20 import com.android.annotations.Nullable; 21 import com.android.ide.common.api.IAttributeInfo; 22 import com.android.ide.common.api.IAttributeInfo.Format; 23 import com.android.ide.eclipse.adt.internal.editors.ui.TextValueCellEditor; 24 import com.android.ide.eclipse.adt.internal.editors.uimodel.UiAttributeNode; 25 import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode; 26 import com.android.ide.eclipse.adt.internal.editors.uimodel.UiTextAttributeNode; 27 import com.android.sdklib.SdkConstants; 28 29 import org.eclipse.jface.viewers.CellEditor; 30 import org.eclipse.jface.viewers.ILabelProvider; 31 import org.eclipse.swt.widgets.Composite; 32 import org.eclipse.swt.widgets.Control; 33 import org.eclipse.ui.views.properties.IPropertyDescriptor; 34 35 import java.util.EnumSet; 36 import java.util.Locale; 37 38 39 /** 40 * Describes a textual XML attribute. 41 * <p/> 42 * Such an attribute has a tooltip and would typically be displayed by 43 * {@link UiTextAttributeNode} using a label widget and text field. 44 * <p/> 45 * This is the "default" kind of attribute. If in doubt, use this. 46 */ 47 public class TextAttributeDescriptor extends AttributeDescriptor implements IPropertyDescriptor { 48 public static final String DEPRECATED_CATEGORY = "Deprecated"; 49 50 private String mUiName; 51 private String mTooltip; 52 private boolean mRequired; 53 54 /** 55 * Creates a new {@link TextAttributeDescriptor} 56 * 57 * @param xmlLocalName The XML name of the attribute (case sensitive) 58 * @param nsUri The URI of the attribute. Can be null if attribute has no namespace. 59 * See {@link SdkConstants#NS_RESOURCES} for a common value. 60 * @param attrInfo The {@link IAttributeInfo} of this attribute. Can't be null. 61 */ 62 public TextAttributeDescriptor( 63 String xmlLocalName, 64 String nsUri, 65 IAttributeInfo attrInfo) { 66 super(xmlLocalName, nsUri, attrInfo); 67 } 68 69 /** 70 * @return The UI name of the attribute. Cannot be an empty string and cannot be null. 71 */ 72 @NonNull 73 public String getUiName() { 74 if (mUiName == null) { 75 IAttributeInfo info = getAttributeInfo(); 76 if (info != null) { 77 mUiName = DescriptorsUtils.prettyAttributeUiName(info.getName()); 78 if (mRequired) { 79 mUiName += "*"; //$NON-NLS-1$ 80 } 81 } else { 82 mUiName = getXmlLocalName(); 83 } 84 } 85 86 return mUiName; 87 } 88 89 90 /** 91 * Sets the UI name to be associated with this descriptor. This is usually 92 * computed lazily from the {@link #getAttributeInfo()} data, but for some 93 * hardcoded/builtin descriptor this is manually initialized. 94 * 95 * @param uiName the new UI name to be used 96 * @return this, for constructor setter chaining 97 */ 98 public TextAttributeDescriptor setUiName(String uiName) { 99 mUiName = uiName; 100 101 return this; 102 } 103 104 /** 105 * Sets the tooltip to be associated with this descriptor. This is usually 106 * computed lazily from the {@link #getAttributeInfo()} data, but for some 107 * hardcoded/builtin descriptor this is manually initialized. 108 * 109 * @param tooltip the new tooltip to be used 110 * @return this, for constructor setter chaining 111 */ 112 public TextAttributeDescriptor setTooltip(String tooltip) { 113 mTooltip = tooltip; 114 115 return this; 116 } 117 118 /** 119 * Sets whether this attribute is required 120 * 121 * @param required whether this attribute is required 122 * @return this, for constructor setter chaining 123 */ 124 public TextAttributeDescriptor setRequired(boolean required) { 125 mRequired = required; 126 127 return this; 128 } 129 130 /** 131 * Returns whether this attribute is required 132 * 133 * @return whether this attribute is required 134 */ 135 public boolean isRequired() { 136 return mRequired; 137 } 138 139 /** 140 * The tooltip string is either null or a non-empty string. 141 * <p/> 142 * The tooltip is based on the Javadoc of the attribute and already processed via 143 * {@link DescriptorsUtils#formatTooltip(String)} to be displayed right away as 144 * a UI tooltip. 145 * <p/> 146 * An empty string is converted to null, to match the behavior of setToolTipText() in 147 * {@link Control}. 148 * 149 * @return A non-empty tooltip string or null 150 */ 151 @Nullable 152 public String getTooltip() { 153 if (mTooltip == null) { 154 IAttributeInfo info = getAttributeInfo(); 155 if (info == null) { 156 mTooltip = ""; 157 return mTooltip; 158 } 159 160 String tooltip = null; 161 String rawTooltip = info.getJavaDoc(); 162 if (rawTooltip == null) { 163 rawTooltip = ""; 164 } 165 166 String deprecated = info.getDeprecatedDoc(); 167 if (deprecated != null) { 168 if (rawTooltip.length() > 0) { 169 rawTooltip += "@@"; //$NON-NLS-1$ insert a break 170 } 171 rawTooltip += "* Deprecated"; 172 if (deprecated.length() != 0) { 173 rawTooltip += ": " + deprecated; //$NON-NLS-1$ 174 } 175 if (deprecated.length() == 0 || !deprecated.endsWith(".")) { //$NON-NLS-1$ 176 rawTooltip += "."; //$NON-NLS-1$ 177 } 178 } 179 180 // Add the known types to the tooltip 181 EnumSet<Format> formats_list = info.getFormats(); 182 int flen = formats_list.size(); 183 if (flen > 0) { 184 StringBuilder sb = new StringBuilder(); 185 if (rawTooltip != null && rawTooltip.length() > 0) { 186 sb.append(rawTooltip); 187 sb.append(" "); //$NON-NLS-1$ 188 } 189 if (sb.length() > 0) { 190 sb.append("@@"); //$NON-NLS-1$ @@ inserts a break before the types 191 } 192 sb.append("["); //$NON-NLS-1$ 193 boolean isFirst = true; 194 for (Format f : formats_list) { 195 if (isFirst) { 196 isFirst = false; 197 } else { 198 sb.append(", "); 199 } 200 sb.append(f.toString().toLowerCase(Locale.US)); 201 } 202 // The extra space at the end makes the tooltip more readable on Windows. 203 sb.append("]"); //$NON-NLS-1$ 204 205 if (mRequired) { 206 // Note: this string is split in 2 to make it translatable. 207 sb.append(".@@"); //$NON-NLS-1$ @@ inserts a break and is not translatable 208 sb.append("* Required."); 209 } 210 211 // The extra space at the end makes the tooltip more readable on Windows. 212 sb.append(" "); //$NON-NLS-1$ 213 214 rawTooltip = sb.toString(); 215 tooltip = DescriptorsUtils.formatTooltip(rawTooltip); 216 } 217 218 if (tooltip == null) { 219 tooltip = DescriptorsUtils.formatTooltip(rawTooltip); 220 } 221 mTooltip = tooltip; 222 } 223 224 return mTooltip.isEmpty() ? null : mTooltip; 225 } 226 227 /** 228 * @return A new {@link UiTextAttributeNode} linked to this descriptor. 229 */ 230 @Override 231 public UiAttributeNode createUiNode(UiElementNode uiParent) { 232 return new UiTextAttributeNode(this, uiParent); 233 } 234 235 // ------- IPropertyDescriptor Methods 236 237 @Override 238 public CellEditor createPropertyEditor(Composite parent) { 239 return new TextValueCellEditor(parent); 240 } 241 242 @Override 243 public String getCategory() { 244 if (isDeprecated()) { 245 return DEPRECATED_CATEGORY; 246 } 247 248 ElementDescriptor parent = getParent(); 249 if (parent != null) { 250 return parent.getUiName(); 251 } 252 253 return null; 254 } 255 256 @Override 257 public String getDescription() { 258 return getTooltip(); 259 } 260 261 @Override 262 public String getDisplayName() { 263 return getUiName(); 264 } 265 266 @Override 267 public String[] getFilterFlags() { 268 return null; 269 } 270 271 @Override 272 public Object getHelpContextIds() { 273 return null; 274 } 275 276 @Override 277 public Object getId() { 278 return this; 279 } 280 281 @Override 282 public ILabelProvider getLabelProvider() { 283 return AttributeDescriptorLabelProvider.getProvider(); 284 } 285 286 @Override 287 public boolean isCompatibleWith(IPropertyDescriptor anotherProperty) { 288 return anotherProperty == this; 289 } 290 } 291