diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateMetadata.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateMetadata.java | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateMetadata.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateMetadata.java new file mode 100644 index 000000000..4ce7d74c2 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateMetadata.java @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.eclipse.org/org/documents/epl-v10.php + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.ide.eclipse.adt.internal.wizards.templates; + +import static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectWizard.ATTR_MIN_API; +import static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectWizard.ATTR_MIN_BUILD_API; +import static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectWizard.ATTR_REVISION; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_BACKGROUND; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_CLIPART_NAME; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_DESCRIPTION; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_FOREGROUND; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_FORMAT; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_NAME; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_PADDING; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_SHAPE; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_SOURCE_TYPE; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_TEXT; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_TRIM; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_TYPE; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_VALUE; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.CURRENT_FORMAT; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.TAG_DEPENDENCY; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.TAG_ICONS; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.TAG_PARAMETER; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.TAG_THUMB; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.TAG_FORMFACTOR; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.TAG_CATEGORY; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.assetstudiolib.GraphicGenerator; +import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.ide.eclipse.adt.internal.assetstudio.AssetType; +import com.android.ide.eclipse.adt.internal.assetstudio.CreateAssetSetWizardState; +import com.android.ide.eclipse.adt.internal.assetstudio.CreateAssetSetWizardState.SourceType; +import com.android.ide.eclipse.adt.internal.editors.IconFactory; +import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils; +import com.android.utils.Pair; +import com.google.common.collect.Lists; + +import org.eclipse.core.resources.IProject; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.RGB; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** An ADT template along with metadata */ +class TemplateMetadata { + private final Document mDocument; + private final List<Parameter> mParameters; + private final Map<String, Parameter> mParameterMap; + private List<Pair<String, Integer>> mDependencies; + private Integer mMinApi; + private Integer mMinBuildApi; + private Integer mRevision; + private boolean mNoIcons; + private CreateAssetSetWizardState mIconState; + private String mFormFactor; + private String mCategory; + + TemplateMetadata(@NonNull Document document) { + mDocument = document; + + NodeList parameters = mDocument.getElementsByTagName(TAG_PARAMETER); + mParameters = new ArrayList<Parameter>(parameters.getLength()); + mParameterMap = new HashMap<String, Parameter>(parameters.getLength()); + for (int index = 0, max = parameters.getLength(); index < max; index++) { + Element element = (Element) parameters.item(index); + Parameter parameter = new Parameter(this, element); + mParameters.add(parameter); + if (parameter.id != null) { + mParameterMap.put(parameter.id, parameter); + } + } + } + + boolean isSupported() { + String versionString = mDocument.getDocumentElement().getAttribute(ATTR_FORMAT); + if (versionString != null && !versionString.isEmpty()) { + try { + int version = Integer.parseInt(versionString); + return version <= CURRENT_FORMAT; + } catch (NumberFormatException nufe) { + return false; + } + } + + // Older templates without version specified: supported + return true; + } + + @Nullable + String getTitle() { + String name = mDocument.getDocumentElement().getAttribute(ATTR_NAME); + if (name != null && !name.isEmpty()) { + return name; + } + + return null; + } + + @Nullable + String getDescription() { + String description = mDocument.getDocumentElement().getAttribute(ATTR_DESCRIPTION); + if (description != null && !description.isEmpty()) { + return description; + } + + return null; + } + + int getMinSdk() { + if (mMinApi == null) { + mMinApi = 1; + String api = mDocument.getDocumentElement().getAttribute(ATTR_MIN_API); + if (api != null && !api.isEmpty()) { + try { + mMinApi = Integer.parseInt(api); + } catch (NumberFormatException nufe) { + // Templates aren't allowed to contain codenames, should always be an integer + AdtPlugin.log(nufe, null); + mMinApi = 1; + } + } + } + + return mMinApi.intValue(); + } + + int getMinBuildApi() { + if (mMinBuildApi == null) { + mMinBuildApi = 1; + String api = mDocument.getDocumentElement().getAttribute(ATTR_MIN_BUILD_API); + if (api != null && !api.isEmpty()) { + try { + mMinBuildApi = Integer.parseInt(api); + } catch (NumberFormatException nufe) { + // Templates aren't allowed to contain codenames, should always be an integer + AdtPlugin.log(nufe, null); + mMinBuildApi = 1; + } + } + } + + return mMinBuildApi.intValue(); + } + + public int getRevision() { + if (mRevision == null) { + mRevision = 1; + String revision = mDocument.getDocumentElement().getAttribute(ATTR_REVISION); + if (revision != null && !revision.isEmpty()) { + try { + mRevision = Integer.parseInt(revision); + } catch (NumberFormatException nufe) { + AdtPlugin.log(nufe, null); + mRevision = 1; + } + } + } + + return mRevision.intValue(); + } + + public String getFormFactor() { + if (mFormFactor == null) { + mFormFactor = "Mobile"; + + NodeList formfactorDeclarations = mDocument.getElementsByTagName(TAG_FORMFACTOR); + if (formfactorDeclarations.getLength() > 0) { + Element element = (Element) formfactorDeclarations.item(0); + String formFactor = element.getAttribute(ATTR_VALUE); + if (formFactor != null && !formFactor.isEmpty()) { + mFormFactor = formFactor; + } + } + } + return mFormFactor; + } + + public String getCategory() { + if (mCategory == null) { + mCategory = ""; + NodeList categories = mDocument.getElementsByTagName(TAG_CATEGORY); + if (categories.getLength() > 0) { + Element element = (Element) categories.item(0); + String category = element.getAttribute(ATTR_VALUE); + if (category != null && !category.isEmpty()) { + mCategory = category; + } + } + } + return mCategory; + } + + /** + * Returns a suitable icon wizard state instance if this wizard requests + * icons to be created, and null otherwise + * + * @return icon wizard state or null + */ + @Nullable + public CreateAssetSetWizardState getIconState(IProject project) { + if (mIconState == null && !mNoIcons) { + NodeList icons = mDocument.getElementsByTagName(TAG_ICONS); + if (icons.getLength() < 1) { + mNoIcons = true; + return null; + } + Element icon = (Element) icons.item(0); + + mIconState = new CreateAssetSetWizardState(); + mIconState.project = project; + + String typeString = getAttributeOrNull(icon, ATTR_TYPE); + if (typeString != null) { + typeString = typeString.toUpperCase(Locale.US); + boolean found = false; + for (AssetType type : AssetType.values()) { + if (typeString.equals(type.name())) { + mIconState.type = type; + found = true; + break; + } + } + if (!found) { + AdtPlugin.log(null, "Unknown asset type %1$s", typeString); + } + } + + mIconState.outputName = getAttributeOrNull(icon, ATTR_NAME); + if (mIconState.outputName != null) { + // Register parameter such that if it is referencing other values, it gets + // updated when other values are edited + Parameter outputParameter = new Parameter(this, + Parameter.Type.STRING, "_iconname", mIconState.outputName); //$NON-NLS-1$ + getParameters().add(outputParameter); + } + + RGB background = getRgb(icon, ATTR_BACKGROUND); + if (background != null) { + mIconState.background = background; + } + RGB foreground = getRgb(icon, ATTR_FOREGROUND); + if (foreground != null) { + mIconState.foreground = foreground; + } + String shapeString = getAttributeOrNull(icon, ATTR_SHAPE); + if (shapeString != null) { + shapeString = shapeString.toUpperCase(Locale.US); + boolean found = false; + for (GraphicGenerator.Shape shape : GraphicGenerator.Shape.values()) { + if (shapeString.equals(shape.name())) { + mIconState.shape = shape; + found = true; + break; + } + } + if (!found) { + AdtPlugin.log(null, "Unknown shape %1$s", shapeString); + } + } + String trimString = getAttributeOrNull(icon, ATTR_TRIM); + if (trimString != null) { + mIconState.trim = Boolean.valueOf(trimString); + } + String paddingString = getAttributeOrNull(icon, ATTR_PADDING); + if (paddingString != null) { + mIconState.padding = Integer.parseInt(paddingString); + } + String sourceTypeString = getAttributeOrNull(icon, ATTR_SOURCE_TYPE); + if (sourceTypeString != null) { + sourceTypeString = sourceTypeString.toUpperCase(Locale.US); + boolean found = false; + for (SourceType type : SourceType.values()) { + if (sourceTypeString.equals(type.name())) { + mIconState.sourceType = type; + found = true; + break; + } + } + if (!found) { + AdtPlugin.log(null, "Unknown source type %1$s", sourceTypeString); + } + } + mIconState.clipartName = getAttributeOrNull(icon, ATTR_CLIPART_NAME); + + String textString = getAttributeOrNull(icon, ATTR_TEXT); + if (textString != null) { + mIconState.text = textString; + } + } + + return mIconState; + } + + void updateIconName(List<Parameter> parameters, StringEvaluator evaluator) { + if (mIconState != null) { + NodeList icons = mDocument.getElementsByTagName(TAG_ICONS); + if (icons.getLength() < 1) { + return; + } + Element icon = (Element) icons.item(0); + String name = getAttributeOrNull(icon, ATTR_NAME); + if (name != null) { + mIconState.outputName = evaluator.evaluate(name, parameters); + } + } + } + + private static RGB getRgb(@NonNull Element element, @NonNull String name) { + String colorString = getAttributeOrNull(element, name); + if (colorString != null) { + int rgb = ImageUtils.getColor(colorString.trim()); + return ImageUtils.intToRgb(rgb); + } + + return null; + } + + @Nullable + private static String getAttributeOrNull(@NonNull Element element, @NonNull String name) { + String value = element.getAttribute(name); + if (value != null && value.isEmpty()) { + return null; + } + return value; + } + + @Nullable + String getThumbnailPath() { + // Apply selector logic. Pick the thumb first thumb that satisfies the largest number + // of conditions. + NodeList thumbs = mDocument.getElementsByTagName(TAG_THUMB); + if (thumbs.getLength() == 0) { + return null; + } + + + int bestMatchCount = 0; + Element bestMatch = null; + + for (int i = 0, n = thumbs.getLength(); i < n; i++) { + Element thumb = (Element) thumbs.item(i); + + NamedNodeMap attributes = thumb.getAttributes(); + if (bestMatch == null && attributes.getLength() == 0) { + bestMatch = thumb; + } else if (attributes.getLength() <= bestMatchCount) { + // Already have a match with this number of attributes, no point checking + continue; + } else { + boolean match = true; + for (int j = 0, max = attributes.getLength(); j < max; j++) { + Attr attribute = (Attr) attributes.item(j); + Parameter parameter = mParameterMap.get(attribute.getName()); + if (parameter == null) { + AdtPlugin.log(null, "Unexpected parameter in template thumbnail: %1$s", + attribute.getName()); + continue; + } + String thumbNailValue = attribute.getValue(); + String editedValue = parameter.value != null ? parameter.value.toString() : ""; + if (!thumbNailValue.equals(editedValue)) { + match = false; + break; + } + } + if (match) { + bestMatch = thumb; + bestMatchCount = attributes.getLength(); + } + } + } + + if (bestMatch != null) { + NodeList children = bestMatch.getChildNodes(); + for (int i = 0, n = children.getLength(); i < n; i++) { + Node child = children.item(i); + if (child.getNodeType() == Node.TEXT_NODE) { + return child.getNodeValue().trim(); + } + } + } + + return null; + } + + /** + * Returns the dependencies (as a list of pairs of names and revisions) + * required by this template + */ + List<Pair<String, Integer>> getDependencies() { + if (mDependencies == null) { + NodeList elements = mDocument.getElementsByTagName(TAG_DEPENDENCY); + if (elements.getLength() == 0) { + return Collections.emptyList(); + } + + List<Pair<String, Integer>> dependencies = Lists.newArrayList(); + for (int i = 0, n = elements.getLength(); i < n; i++) { + Element element = (Element) elements.item(i); + String name = element.getAttribute(ATTR_NAME); + int revision = -1; + String revisionString = element.getAttribute(ATTR_REVISION); + if (!revisionString.isEmpty()) { + revision = Integer.parseInt(revisionString); + } + dependencies.add(Pair.of(name, revision)); + } + mDependencies = dependencies; + } + + return mDependencies; + } + + /** Returns the list of available parameters */ + @NonNull + List<Parameter> getParameters() { + return mParameters; + } + + /** + * Returns the parameter of the given id, or null if not found + * + * @param id the id of the target parameter + * @return the corresponding parameter, or null if not found + */ + @Nullable + public Parameter getParameter(@NonNull String id) { + for (Parameter parameter : mParameters) { + if (id.equals(parameter.id)) { + return parameter; + } + } + + return null; + } + + /** Returns a default icon for templates */ + static Image getDefaultTemplateIcon() { + return IconFactory.getInstance().getIcon("default_template"); //$NON-NLS-1$ + } +} |