diff options
46 files changed, 744 insertions, 283 deletions
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java index c2942d0..233c7c1 100644 --- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java +++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java @@ -41,6 +41,8 @@ import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.ModifyEvent; @@ -52,6 +54,7 @@ import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; @@ -92,6 +95,15 @@ public final class LogCatPanel extends SelectionDependentPanel /** Preference key to use for storing font settings. */ public static final String LOGCAT_VIEW_FONT_PREFKEY = "logcat.view.font"; + // Preference keys for message colors based on severity level + private static final String MSG_COLOR_PREFKEY_PREFIX = "logcat.msg.color."; + public static final String VERBOSE_COLOR_PREFKEY = MSG_COLOR_PREFKEY_PREFIX + "verbose"; //$NON-NLS-1$ + public static final String DEBUG_COLOR_PREFKEY = MSG_COLOR_PREFKEY_PREFIX + "debug"; //$NON-NLS-1$ + public static final String INFO_COLOR_PREFKEY = MSG_COLOR_PREFKEY_PREFIX + "info"; //$NON-NLS-1$ + public static final String WARN_COLOR_PREFKEY = MSG_COLOR_PREFKEY_PREFIX + "warn"; //$NON-NLS-1$ + public static final String ERROR_COLOR_PREFKEY = MSG_COLOR_PREFKEY_PREFIX + "error"; //$NON-NLS-1$ + public static final String ASSERT_COLOR_PREFKEY = MSG_COLOR_PREFKEY_PREFIX + "assert"; //$NON-NLS-1$ + // Use a monospace font family private static final String FONT_FAMILY = DdmConstants.CURRENT_PLATFORM == DdmConstants.PLATFORM_DARWIN ? "Monaco":"Courier New"; @@ -163,6 +175,13 @@ public final class LogCatPanel extends SelectionDependentPanel private Font mFont; private int mWrapWidthInChars; + private Color mVerboseColor; + private Color mDebugColor; + private Color mInfoColor; + private Color mWarnColor; + private Color mErrorColor; + private Color mAssertColor; + private SashForm mSash; // messages added since last refresh, synchronized on mLogBuffer @@ -185,6 +204,20 @@ public final class LogCatPanel extends SelectionDependentPanel initializePreferenceUpdateListeners(); mFont = getFontFromPrefStore(); + loadMessageColorPreferences(); + } + + private void loadMessageColorPreferences() { + if (mVerboseColor != null) { + disposeMessageColors(); + } + + mVerboseColor = getColorFromPrefStore(VERBOSE_COLOR_PREFKEY); + mDebugColor = getColorFromPrefStore(DEBUG_COLOR_PREFKEY); + mInfoColor = getColorFromPrefStore(INFO_COLOR_PREFKEY); + mWarnColor = getColorFromPrefStore(WARN_COLOR_PREFKEY); + mErrorColor = getColorFromPrefStore(ERROR_COLOR_PREFKEY); + mAssertColor = getColorFromPrefStore(ASSERT_COLOR_PREFKEY); } private void initializeFilters() { @@ -209,6 +242,20 @@ public final class LogCatPanel extends SelectionDependentPanel mPrefStore.setDefault(LogCatMessageList.MAX_MESSAGES_PREFKEY, LogCatMessageList.MAX_MESSAGES_DEFAULT); mPrefStore.setDefault(DISPLAY_FILTERS_COLUMN_PREFKEY, true); + + /* Default Colors for different log levels. */ + PreferenceConverter.setDefault(mPrefStore, LogCatPanel.VERBOSE_COLOR_PREFKEY, + new RGB(0, 0, 0)); + PreferenceConverter.setDefault(mPrefStore, LogCatPanel.DEBUG_COLOR_PREFKEY, + new RGB(0, 0, 127)); + PreferenceConverter.setDefault(mPrefStore, LogCatPanel.INFO_COLOR_PREFKEY, + new RGB(0, 127, 0)); + PreferenceConverter.setDefault(mPrefStore, LogCatPanel.WARN_COLOR_PREFKEY, + new RGB(255, 127, 0)); + PreferenceConverter.setDefault(mPrefStore, LogCatPanel.ERROR_COLOR_PREFKEY, + new RGB(255, 0, 0)); + PreferenceConverter.setDefault(mPrefStore, LogCatPanel.ASSERT_COLOR_PREFKEY, + new RGB(255, 0, 0)); } private void initializePreferenceUpdateListeners() { @@ -230,6 +277,21 @@ public final class LogCatPanel extends SelectionDependentPanel } } }); + } else if (changedProperty.startsWith(MSG_COLOR_PREFKEY_PREFIX)) { + loadMessageColorPreferences(); + Display.getDefault().syncExec(new Runnable() { + @Override + public void run() { + Color c = mVerboseColor; + for (TableItem it: mTable.getItems()) { + Object data = it.getData(); + if (data instanceof LogCatMessage) { + c = getForegroundColor((LogCatMessage) data); + } + it.setForeground(c); + } + } + }); } else if (changedProperty.equals(LogCatMessageList.MAX_MESSAGES_PREFKEY)) { mReceiver.resizeFifo(mPrefStore.getInt( LogCatMessageList.MAX_MESSAGES_PREFKEY)); @@ -834,6 +896,13 @@ public final class LogCatPanel extends SelectionDependentPanel addRightClickMenu(mTable); initDoubleClickListener(); recomputeWrapWidth(); + + mTable.addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent arg0) { + dispose(); + } + }); } /** Setup menu to be displayed when right clicking a log message. */ @@ -914,6 +983,11 @@ public final class LogCatPanel extends SelectionDependentPanel return new Font(Display.getDefault(), fd); } + private Color getColorFromPrefStore(String key) { + RGB rgb = PreferenceConverter.getColor(mPrefStore, key); + return new Color(Display.getDefault(), rgb); + } + private void setupDefaults() { int defaultFilterIndex = 0; mFiltersTableViewer.getTable().setSelection(defaultFilterIndex); @@ -1239,29 +1313,24 @@ public final class LogCatPanel extends SelectionDependentPanel return wrappedMessages; } - /* Default Colors for different log levels. */ - private static final Color INFO_MSG_COLOR = new Color(null, 0, 127, 0); - private static final Color DEBUG_MSG_COLOR = new Color(null, 0, 0, 127); - private static final Color ERROR_MSG_COLOR = new Color(null, 255, 0, 0); - private static final Color WARN_MSG_COLOR = new Color(null, 255, 127, 0); - private static final Color VERBOSE_MSG_COLOR = new Color(null, 0, 0, 0); - - private static Color getForegroundColor(LogCatMessage m) { + private Color getForegroundColor(LogCatMessage m) { LogLevel l = m.getLogLevel(); if (l.equals(LogLevel.VERBOSE)) { - return VERBOSE_MSG_COLOR; + return mVerboseColor; } else if (l.equals(LogLevel.INFO)) { - return INFO_MSG_COLOR; + return mInfoColor; } else if (l.equals(LogLevel.DEBUG)) { - return DEBUG_MSG_COLOR; + return mDebugColor; } else if (l.equals(LogLevel.ERROR)) { - return ERROR_MSG_COLOR; + return mErrorColor; } else if (l.equals(LogLevel.WARN)) { - return WARN_MSG_COLOR; + return mWarnColor; + } else if (l.equals(LogLevel.ASSERT)) { + return mAssertColor; } - return null; + return mVerboseColor; } private List<ILogCatMessageSelectionListener> mMessageSelectionListeners; @@ -1344,4 +1413,23 @@ public final class LogCatPanel extends SelectionDependentPanel public void selectAll() { mTable.selectAll(); } + + private void dispose() { + if (mFont != null && !mFont.isDisposed()) { + mFont.dispose(); + } + + if (mVerboseColor != null && !mVerboseColor.isDisposed()) { + disposeMessageColors(); + } + } + + private void disposeMessageColors() { + mVerboseColor.dispose(); + mDebugColor.dispose(); + mInfoColor.dispose(); + mWarnColor.dispose(); + mErrorColor.dispose(); + mAssertColor.dispose(); + } } diff --git a/eclipse/dictionary.txt b/eclipse/dictionary.txt index cbf3d10..dbb51e5 100644 --- a/eclipse/dictionary.txt +++ b/eclipse/dictionary.txt @@ -292,7 +292,9 @@ textfields thematically themed thumbnail +thumbnails timestamp +timestamps tmp toolbar tooltip diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java index 8bf09f1..09092e7 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtUtils.java @@ -799,6 +799,17 @@ public class AdtUtils { } /** + * Returns the highest known API level to this version of ADT. The + * {@link #getAndroidName(int)} method will return real names up to and + * including this number. + * + * @return the highest known API number + */ + public static int getHighestKnownApiLevel() { + return 15; + } + + /** * Returns a list of known API names * * @return a list of string API names, starting from 1 and up through the diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java index 803478b..396e172 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java @@ -1018,23 +1018,21 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh model.changedModel(); if (AdtPrefs.getPrefs().getFormatGuiXml() && mFormatNode != null) { - if (!mFormatNode.hasError()) { - if (mFormatNode == getUiRootNode()) { - reformatDocument(); - } else { - Node node = mFormatNode.getXmlNode(); - if (node instanceof IndexedRegion) { - IndexedRegion region = (IndexedRegion) node; - int begin = region.getStartOffset(); - int end = region.getEndOffset(); - - if (!mFormatChildren) { - // This will format just the attribute list - end = begin + 1; - } - - reformatRegion(begin, end); + if (mFormatNode == getUiRootNode()) { + reformatDocument(); + } else { + Node node = mFormatNode.getXmlNode(); + if (node instanceof IndexedRegion) { + IndexedRegion region = (IndexedRegion) node; + int begin = region.getStartOffset(); + int end = region.getEndOffset(); + + if (!mFormatChildren) { + // This will format just the attribute list + end = begin + 1; } + + reformatRegion(begin, end); } } mFormatNode = null; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/Hyperlinks.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/Hyperlinks.java index 6e035af..c63ed18 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/Hyperlinks.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/Hyperlinks.java @@ -16,14 +16,15 @@ package com.android.ide.eclipse.adt.internal.editors; -import static com.android.util.XmlUtils.ANDROID_URI; import static com.android.ide.common.layout.LayoutConstants.ATTR_CLASS; import static com.android.ide.common.layout.LayoutConstants.ATTR_NAME; import static com.android.ide.common.layout.LayoutConstants.ATTR_ON_CLICK; import static com.android.ide.common.layout.LayoutConstants.NEW_ID_PREFIX; import static com.android.ide.common.layout.LayoutConstants.VIEW; import static com.android.ide.common.resources.ResourceResolver.PREFIX_ANDROID_RESOURCE_REF; +import static com.android.ide.common.resources.ResourceResolver.PREFIX_ANDROID_THEME_REF; import static com.android.ide.common.resources.ResourceResolver.PREFIX_RESOURCE_REF; +import static com.android.ide.common.resources.ResourceResolver.PREFIX_THEME_REF; import static com.android.ide.eclipse.adt.AdtConstants.ANDROID_PKG; import static com.android.ide.eclipse.adt.AdtConstants.EXT_XML; import static com.android.ide.eclipse.adt.AdtConstants.FN_RESOURCE_BASE; @@ -38,6 +39,10 @@ import static com.android.sdklib.xml.AndroidManifest.ATTRIBUTE_NAME; import static com.android.sdklib.xml.AndroidManifest.ATTRIBUTE_PACKAGE; import static com.android.sdklib.xml.AndroidManifest.NODE_ACTIVITY; import static com.android.sdklib.xml.AndroidManifest.NODE_SERVICE; +import static com.android.tools.lint.detector.api.LintConstants.ANDROID_STYLE_RESOURCE_PREFIX; +import static com.android.tools.lint.detector.api.LintConstants.NEW_ID_RESOURCE_PREFIX; +import static com.android.tools.lint.detector.api.LintConstants.STYLE_RESOURCE_PREFIX; +import static com.android.util.XmlUtils.ANDROID_URI; import com.android.annotations.NonNull; import com.android.annotations.Nullable; @@ -210,14 +215,14 @@ public class Hyperlinks { } String value = attribute.getValue(); - if (value.startsWith("@+")) { //$NON-NLS-1$ + if (value.startsWith(NEW_ID_RESOURCE_PREFIX)) { // It's a value -declaration-, nowhere else to jump // (though we could consider jumping to the R-file; would that // be helpful?) return false; } - Pair<ResourceType,String> resource = ResourceHelper.parseResource(value); + Pair<ResourceType,String> resource = parseResource(value); if (resource != null) { ResourceType type = resource.getFirst(); if (type != null) { @@ -1026,23 +1031,28 @@ public class Hyperlinks { if (type == ResourceType.ID) { // Ids are recorded in <item> tags instead of <id> tags targetTag = "item"; //$NON-NLS-1$ - } else if (type == ResourceType.ATTR) { + } + + Pair<File, Integer> result = findTag(name, file, parser, document, targetTag); + if (result == null && type == ResourceType.ATTR) { // Attributes seem to be defined in <public> tags targetTag = "public"; //$NON-NLS-1$ + result = findTag(name, file, parser, document, targetTag); } - Element root = document.getDocumentElement(); - if (root.getTagName().equals(ROOT_ELEMENT)) { - NodeList children = root.getChildNodes(); - for (int i = 0, n = children.getLength(); i < n; i++) { - Node child = children.item(i); - if (child.getNodeType() == Node.ELEMENT_NODE) { - Element element = (Element) child; - if (element.getTagName().equals(targetTag)) { - String elementName = element.getAttribute(NAME_ATTR); - if (elementName.equals(name)) { + return result; + } - return Pair.of(file, parser.getOffset(element)); - } + private static Pair<File, Integer> findTag(String name, File file, OffsetTrackingParser parser, + Document document, String targetTag) { + NodeList children = document.getElementsByTagName(targetTag); + for (int i = 0, n = children.getLength(); i < n; i++) { + Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + Element element = (Element) child; + if (element.getTagName().equals(targetTag)) { + String elementName = element.getAttribute(NAME_ATTR); + if (elementName.equals(name)) { + return Pair.of(file, parser.getOffset(element)); } } } @@ -1067,15 +1077,17 @@ public class Hyperlinks { } } - Pair<ResourceType,String> resource = ResourceHelper.parseResource(url); + Pair<ResourceType,String> resource = parseResource(url); if (resource == null) { - String androidStyle = "@android:style/"; //$NON-NLS-1$ + String androidStyle = ANDROID_STYLE_RESOURCE_PREFIX; if (url.startsWith(PREFIX_ANDROID_RESOURCE_REF)) { url = androidStyle + url.substring(PREFIX_ANDROID_RESOURCE_REF.length()); + } else if (url.startsWith(PREFIX_ANDROID_THEME_REF)) { + url = androidStyle + url.substring(PREFIX_ANDROID_THEME_REF.length()); } else if (url.startsWith(ANDROID_PKG + ':')) { url = androidStyle + url.substring(ANDROID_PKG.length() + 1); } else { - url = "@style/" + url; //$NON-NLS-1$ + url = STYLE_RESOURCE_PREFIX + url; } } return getResourceLinks(range, url); @@ -1087,6 +1099,16 @@ public class Hyperlinks { return getResourceLinks(range, url, project, configuration); } + /** Parse a resource reference or a theme reference and return the individual parts */ + private static Pair<ResourceType,String> parseResource(String url) { + if (url.startsWith(PREFIX_THEME_REF)) { + url = PREFIX_RESOURCE_REF + url.substring(PREFIX_THEME_REF.length()); + return ResourceHelper.parseResource(url); + } + + return ResourceHelper.parseResource(url); + } + /** * Computes hyperlinks to resource definitions for resource urls (e.g. * {@code @android:string/ok} or {@code @layout/foo}. May create multiple links. @@ -1101,14 +1123,15 @@ public class Hyperlinks { @NonNull IProject project, @Nullable FolderConfiguration configuration) { List<IHyperlink> links = new ArrayList<IHyperlink>(); - Pair<ResourceType,String> resource = ResourceHelper.parseResource(url); + Pair<ResourceType,String> resource = parseResource(url); if (resource == null || resource.getFirst() == null) { return null; } ResourceType type = resource.getFirst(); String name = resource.getSecond(); - boolean isFramework = url.startsWith("@android"); //$NON-NLS-1$ + boolean isFramework = url.startsWith(PREFIX_ANDROID_RESOURCE_REF) + || url.startsWith(PREFIX_ANDROID_THEME_REF); if (project == null) { // Local reference *within* a framework isFramework = true; @@ -1217,10 +1240,10 @@ public class Hyperlinks { return getStyleLinks(context, range, attribute.getValue()); } if (attribute != null - && attribute.getValue().startsWith(PREFIX_RESOURCE_REF)) { + && (attribute.getValue().startsWith(PREFIX_RESOURCE_REF) + || attribute.getValue().startsWith(PREFIX_THEME_REF))) { // Instantly create links for resources since we can use the existing // resolved maps for this and offer multiple choices for the user - String url = attribute.getValue(); return getResourceLinks(range, url); } @@ -1253,7 +1276,7 @@ public class Hyperlinks { int offset = caretOffset; while (offset > lineStart) { char c = document.getChar(offset); - if (c == '@') { + if (c == '@' || c == '?') { urlStart = offset; break; } else if (!isValidResourceUrlChar(c)) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/ElementDescriptor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/ElementDescriptor.java index 613a68f..7cfe791 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/ElementDescriptor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/descriptors/ElementDescriptor.java @@ -469,4 +469,17 @@ public class ElementDescriptor implements Comparable<ElementDescriptor> { public int compareTo(ElementDescriptor o) { return mUiName.compareToIgnoreCase(o.mUiName); } + + /** + * Ensures that this view descriptor's attribute list is up to date. This is + * always the case for all the builtin descriptors, but for example for a + * custom view, it could be changing dynamically so caches may have to be + * recomputed. This method will return true if nothing changed, and false if + * it recomputed its info. + * + * @return true if the attributes are already up to date and nothing changed + */ + public boolean syncAttributes() { + return true; + } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditorDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditorDelegate.java index 8f50001..89dd263 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditorDelegate.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditorDelegate.java @@ -472,7 +472,10 @@ public class LayoutEditorDelegate extends CommonXmlDelegate } if (job != null) { - job.addJobChangeListener(new LintJobListener(getGraphicalEditor())); + GraphicalEditorPart graphicalEditor = getGraphicalEditor(); + if (graphicalEditor != null) { + job.addJobChangeListener(new LintJobListener(graphicalEditor)); + } } return job; } @@ -483,7 +486,7 @@ public class LayoutEditorDelegate extends CommonXmlDelegate LintJobListener(GraphicalEditorPart editor) { mEditor = editor; - mCanvas = editor.getCanvasControl();; + mCanvas = editor.getCanvasControl(); } @Override diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java index 1fa3f06..5330752 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java @@ -1020,7 +1020,11 @@ public class ConfigurationComposite extends Composite implements SelectionListen } private IAndroidTarget getSelectedTarget() { - return (IAndroidTarget) mTargetCombo.getData(); + if (!mTargetCombo.isDisposed()) { + return (IAndroidTarget) mTargetCombo.getData(); + } + + return null; } void selectTheme(String theme) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/CustomViewDescriptorService.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/CustomViewDescriptorService.java index a110c65..ab4e1e9 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/CustomViewDescriptorService.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/descriptors/CustomViewDescriptorService.java @@ -16,11 +16,11 @@ package com.android.ide.eclipse.adt.internal.editors.layout.descriptors; -import static com.android.util.XmlUtils.ANDROID_URI; import static com.android.sdklib.SdkConstants.CLASS_VIEWGROUP; import static com.android.tools.lint.detector.api.LintConstants.AUTO_URI; import static com.android.tools.lint.detector.api.LintConstants.URI_PREFIX; import static com.android.util.XmlUtils.ANDROID_NS_NAME_PREFIX; +import static com.android.util.XmlUtils.ANDROID_URI; import com.android.annotations.NonNull; import com.android.annotations.Nullable; @@ -44,12 +44,14 @@ import com.android.ide.eclipse.adt.internal.sdk.ProjectState; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.resources.ResourceType; import com.android.sdklib.IAndroidTarget; +import com.google.common.collect.Maps; import com.google.common.collect.ObjectArrays; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jdt.core.IClassFile; @@ -193,7 +195,8 @@ public final class CustomViewDescriptorService { // we have a valid parent, lets create a new ViewElementDescriptor. List<AttributeDescriptor> attrList = new ArrayList<AttributeDescriptor>(); List<AttributeDescriptor> paramList = new ArrayList<AttributeDescriptor>(); - findCustomDescriptors(project, type, attrList, paramList); + Map<ResourceFile, Long> files = findCustomDescriptors(project, type, + attrList, paramList); AttributeDescriptor[] attributes = getAttributeDescriptor(type, parentDescriptor); @@ -209,7 +212,8 @@ public final class CustomViewDescriptorService { ViewElementDescriptor descriptor = new CustomViewDescriptor(name, fqcn, attributes, layoutAttributes, - parentDescriptor.getChildren()); + parentDescriptor.getChildren(), + project, files); descriptor.setSuperClass(parentDescriptor); synchronized (mCustomDescriptorMap) { @@ -270,7 +274,7 @@ public final class CustomViewDescriptorService { } /** Compute/find the styleable resources for the given type, if possible */ - private void findCustomDescriptors( + private Map<ResourceFile, Long> findCustomDescriptors( IProject project, IType type, List<AttributeDescriptor> customAttributes, @@ -286,6 +290,8 @@ public final class CustomViewDescriptorService { Set<ResourceFile> resourceFiles = findAttrsFiles(library, className); if (resourceFiles != null && resourceFiles.size() > 0) { String appUri = getAppResUri(project); + Map<ResourceFile, Long> timestamps = + Maps.newHashMapWithExpectedSize(resourceFiles.size()); for (ResourceFile file : resourceFiles) { AttrsXmlParser attrsXmlParser = getParser(file); String fqcn = type.getFullyQualifiedName(); @@ -300,8 +306,14 @@ public final class CustomViewDescriptorService { classInfo, "Layout", null /*superClassInfo*/); //$NON-NLS-1$ attrsXmlParser.loadLayoutParamsAttributes(layoutInfo); appendAttributes(customLayoutAttributes, layoutInfo.getAttributes(), appUri); + + timestamps.put(file, file.getFile().getModificationStamp()); } + + return timestamps; } + + return null; } /** @@ -309,7 +321,7 @@ public final class CustomViewDescriptorService { * attributes for the given class name */ @Nullable - private Set<ResourceFile> findAttrsFiles(IProject library, String className) { + private static Set<ResourceFile> findAttrsFiles(IProject library, String className) { Set<ResourceFile> resourceFiles = null; ResourceManager manager = ResourceManager.getInstance(); ProjectResources resources = manager.getProjectResources(library); @@ -338,7 +350,7 @@ public final class CustomViewDescriptorService { * attrs.xml file in the same project. */ @Nullable - private IProject getProjectDeclaringType(IType type) { + private static IProject getProjectDeclaringType(IType type) { IClassFile classFile = type.getClassFile(); if (classFile != null) { IPath path = classFile.getPath(); @@ -358,7 +370,7 @@ public final class CustomViewDescriptorService { } /** Returns the name space to use for application attributes */ - private String getAppResUri(IProject project) { + private static String getAppResUri(IProject project) { String appResource; ProjectState projectState = Sdk.getProjectState(project); if (projectState != null && projectState.isLibrary()) { @@ -459,7 +471,7 @@ public final class CustomViewDescriptorService { ViewElementDescriptor descriptor = new CustomViewDescriptor(name, fqcn, getAttributeDescriptor(type, parentDescriptor), getLayoutAttributeDescriptors(type, parentDescriptor), - children); + children, project, null); descriptor.setSuperClass(parentDescriptor); // add it to the map @@ -504,10 +516,14 @@ public final class CustomViewDescriptorService { return parentDescriptor.getLayoutAttributes(); } - private static class CustomViewDescriptor extends ViewElementDescriptor { + private class CustomViewDescriptor extends ViewElementDescriptor { + private Map<ResourceFile, Long> mTimeStamps; + private IProject mProject; + public CustomViewDescriptor(String name, String fqcn, AttributeDescriptor[] attributes, AttributeDescriptor[] layoutAttributes, - ElementDescriptor[] children) { + ElementDescriptor[] children, IProject project, + Map<ResourceFile, Long> timestamps) { super( fqcn, // xml name name, // ui name @@ -519,6 +535,8 @@ public final class CustomViewDescriptorService { children, false // mandatory ); + mTimeStamps = timestamps; + mProject = project; } @Override @@ -533,5 +551,71 @@ public final class CustomViewDescriptorService { return iconFactory.getIcon("customView"); //$NON-NLS-1$ } + + @Override + public boolean syncAttributes() { + // Check if any of the descriptors + if (mTimeStamps != null) { + // Prevent checking actual file timestamps too frequently on rapid burst calls + long now = System.currentTimeMillis(); + if (now - sLastCheck < 1000) { + return true; + } + sLastCheck = now; + + // Check whether the resource files (typically just one) which defined + // custom attributes for this custom view have changed, and if so, + // refresh the attribute descriptors. + // This doesn't work the cases where you add descriptors for a custom + // view after using it, or add attributes in a separate file, but those + // scenarios aren't quite as common (and would require a bit more expensive + // analysis.) + for (Map.Entry<ResourceFile, Long> entry : mTimeStamps.entrySet()) { + ResourceFile file = entry.getKey(); + Long timestamp = entry.getValue(); + boolean recompute = false; + if (file.getFile().getModificationStamp() > timestamp.longValue()) { + // One or more attributes changed: recompute + recompute = true; + mParserCache.remove(file); + } + + if (recompute) { + IJavaProject javaProject = JavaCore.create(mProject); + String fqcn = getFullClassName(); + IType type = null; + try { + type = javaProject.findType(fqcn); + } catch (CoreException e) { + AdtPlugin.log(e, null); + } + if (type == null || !type.exists()) { + return true; + } + + List<AttributeDescriptor> attrList = new ArrayList<AttributeDescriptor>(); + List<AttributeDescriptor> paramList = new ArrayList<AttributeDescriptor>(); + + mTimeStamps = findCustomDescriptors(mProject, type, attrList, paramList); + + ViewElementDescriptor parentDescriptor = getSuperClassDesc(); + AttributeDescriptor[] attributes = + getAttributeDescriptor(type, parentDescriptor); + if (!attrList.isEmpty()) { + attributes = join(attrList, attributes); + } + attributes = attrList.toArray(new AttributeDescriptor[attrList.size()]); + setAttributes(attributes); + + return false; + } + } + } + + return true; + } } + + /** Timestamp of the most recent {@link CustomViewDescriptor#syncAttributes} check */ + private static long sLastCheck; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java index 954305e..2154179 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvas.java @@ -663,7 +663,11 @@ public class LayoutCanvas extends Canvas { * rendered image, but it will never zoom in. */ void setFitScale(boolean onlyZoomOut) { - Image image = getImageOverlay().getImage(); + ImageOverlay imageOverlay = getImageOverlay(); + if (imageOverlay == null) { + return; + } + Image image = imageOverlay.getImage(); if (image != null) { Rectangle canvasSize = getClientArea(); int canvasWidth = canvasSize.width; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java index 8b017f2..9261aff 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/OutlinePage.java @@ -261,7 +261,13 @@ public class OutlinePage extends ContentOutlinePage /** Refresh all the icon state */ public void refreshIcons() { - getTreeViewer().refresh(); + TreeViewer treeViewer = getTreeViewer(); + if (treeViewer != null) { + Tree tree = treeViewer.getTree(); + if (tree != null && !tree.isDisposed()) { + treeViewer.refresh(); + } + } } /** @@ -730,7 +736,8 @@ public class OutlinePage extends ContentOutlinePage // Temporary diagnostics code when developing GridLayout if (GridLayoutRule.sDebugGridLayout) { String namespace; - if (e.getParentNode().getNodeName().equals(GRID_LAYOUT)) { + if (e.getParentNode() != null + && e.getParentNode().getNodeName().equals(GRID_LAYOUT)) { namespace = ANDROID_URI; } else { IProject project = mGraphicalEditorPart.getProject(); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java index 74bc4f5..9b0d7a6 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java @@ -144,15 +144,20 @@ class RenderLogger extends LayoutLog { @Override public void warning(String tag, String message, Object data) { String description = describe(message); - AdtPlugin.log(IStatus.WARNING, "%1$s: %2$s", mName, description); + boolean log = true; if (TAG_RESOURCES_FORMAT.equals(tag)) { if (description.equals("You must supply a layout_width attribute.") //$NON-NLS-1$ || description.equals("You must supply a layout_height attribute.")) {//$NON-NLS-1$ tag = TAG_MISSING_DIMENSION; + log = false; } } + if (log) { + AdtPlugin.log(IStatus.WARNING, "%1$s: %2$s", mName, description); + } + addWarning(tag, description); } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java index ec19ea7..fef6022 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java @@ -66,6 +66,9 @@ public class UiViewElementNode extends UiElementNode { */ @Override public AttributeDescriptor[] getAttributeDescriptors() { + if (!getDescriptor().syncAttributes()) { + mCachedAttributeDescriptors = null; + } if (mCachedAttributeDescriptors != null) { return mCachedAttributeDescriptors; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java index 64b22a2..22737e1 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestContentAssist.java @@ -17,8 +17,10 @@ package com.android.ide.eclipse.adt.internal.editors.manifest; import static com.android.sdklib.xml.AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION; +import static com.android.sdklib.xml.AndroidManifest.ATTRIBUTE_TARGET_SDK_VERSION; import com.android.annotations.VisibleForTesting; +import com.android.ide.eclipse.adt.AdtUtils; import com.android.ide.eclipse.adt.internal.editors.AndroidContentAssist; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; import com.android.ide.eclipse.adt.internal.sdk.Sdk; @@ -30,9 +32,7 @@ import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.w3c.dom.Node; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; /** * Content Assist Processor for AndroidManifest.xml @@ -51,41 +51,31 @@ public final class ManifestContentAssist extends AndroidContentAssist { protected void computeAttributeValues(List<ICompletionProposal> proposals, int offset, String parentTagName, String attributeName, Node node, String wordPrefix, boolean skipEndTag, int replaceLength) { - if (attributeName.endsWith(':' + ATTRIBUTE_MIN_SDK_VERSION)) { + if (attributeName.endsWith(ATTRIBUTE_MIN_SDK_VERSION) + || attributeName.endsWith(ATTRIBUTE_TARGET_SDK_VERSION)) { // The user is completing the minSdkVersion attribute: it should be // an integer for the API version, but we'll add full Android version // names to make it more obvious what they're selecting List<Pair<String, String>> choices = new ArrayList<Pair<String, String>>(); - // Max: Look up what versions I have + int max = AdtUtils.getHighestKnownApiLevel(); + // Look for any more recent installed versions the user may have IAndroidTarget[] targets = Sdk.getCurrent().getTargets(); - Map<String, IAndroidTarget> versionMap = new HashMap<String, IAndroidTarget>(); - List<String> codeNames = new ArrayList<String>(); - int maxVersion = 1; for (IAndroidTarget target : targets) { AndroidVersion version = target.getVersion(); int apiLevel = version.getApiLevel(); - String key; - if (version.isPreview()) { - key = version.getCodename(); - codeNames.add(key); - apiLevel--; - } else { - key = Integer.toString(apiLevel); + if (apiLevel > max) { + if (version.isPreview()) { + // Use codename, not API level, as version string for preview versions + choices.add(Pair.of(version.getCodename(), version.getCodename())); + } else { + choices.add(Pair.of(Integer.toString(apiLevel), target.getFullName())); + } } - if (apiLevel > maxVersion) { - maxVersion = apiLevel; - } - - versionMap.put(key, target); - } - for (String codeName : codeNames) { - choices.add(Pair.<String, String>of(codeName, null)); } - for (int i = maxVersion; i >= 1; i--) { - IAndroidTarget target = versionMap.get(Integer.toString(i)); - String version = target != null ? target.getFullName() : null; - choices.add(Pair.of(Integer.toString(i), version)); + for (int api = max; api >= 1; api--) { + String name = AdtUtils.getAndroidName(api); + choices.add(Pair.of(Integer.toString(api), name)); } char needTag = 0; addMatchingProposals(proposals, choices.toArray(), offset, node, wordPrefix, diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiModelTreeLabelProvider.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiModelTreeLabelProvider.java index f2ab512..3373197 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiModelTreeLabelProvider.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiModelTreeLabelProvider.java @@ -17,8 +17,8 @@ package com.android.ide.eclipse.adt.internal.editors.ui.tree; import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.ide.eclipse.adt.internal.editors.IconFactory; import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor; -import com.android.ide.eclipse.adt.internal.editors.ui.ErrorImageComposite; import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode; import org.eclipse.jface.viewers.ILabelProvider; @@ -56,8 +56,7 @@ public class UiModelTreeLabelProvider implements ILabelProvider { Image img = desc.getCustomizedIcon(); if (img != null) { if (node != null && node.hasError()) { - //TODO: cache image - return new ErrorImageComposite(img).createImage(); + return IconFactory.getInstance().addErrorIcon(img); } else { return img; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java index f1c9b1a..4cad83e 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/values/ValuesContentAssist.java @@ -201,7 +201,9 @@ public class ValuesContentAssist extends AndroidContentAssist { } } } - } else if (parentNode.getNodeName().equals(ITEM_TAG)) { + } + + if (parentNode.getNodeName().equals(ITEM_TAG)) { // Completing text content inside an <item> tag: offer @resource completion. if (prefix.startsWith(PREFIX_RESOURCE_REF) || prefix.trim().length() == 0) { String[] choices = UiResourceAttributeNode.computeResourceStringMatches( diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintListDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintListDialog.java index bd42906..147327d 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintListDialog.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintListDialog.java @@ -20,6 +20,7 @@ import com.android.annotations.Nullable; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtUtils; import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; +import com.android.ide.eclipse.adt.internal.editors.IconFactory; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; @@ -53,7 +54,7 @@ import java.util.Set; @SuppressWarnings("restriction") // WST DOM access class LintListDialog extends TitleAreaDialog implements SelectionListener { - private static final String PROJECT_LOGO_LARGE = "icons/android-64.png"; //$NON-NLS-1$ + private static final String PROJECT_LOGO_LARGE = "android-64"; //$NON-NLS-1$ private final IFile mFile; private final IEditorPart mEditor; private Button mFixButton; @@ -90,7 +91,8 @@ class LintListDialog extends TitleAreaDialog implements SelectionListener { Control contents = super.createContents(parent); setTitle("Lint Warnings in Layout"); setMessage("Lint Errors found for the current layout:"); - setTitleImage(AdtPlugin.getImageDescriptor(PROJECT_LOGO_LARGE).createImage()); + setTitleImage(IconFactory.getInstance().getIcon(PROJECT_LOGO_LARGE)); + return contents; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java index 22eb81a..9a61b4f 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java @@ -16,9 +16,6 @@ package com.android.ide.eclipse.adt.internal.wizards.templates; import static com.android.ide.eclipse.adt.internal.wizards.templates.NewTemplateWizard.ACTIVITY_TEMPLATES; -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_NAME; -import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_THUMB; import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.PREVIEW_PADDING; import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.PREVIEW_WIDTH; @@ -41,8 +38,6 @@ import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.List; -import org.w3c.dom.Document; -import org.w3c.dom.Element; import java.io.InputStream; @@ -121,18 +116,17 @@ class ActivityPage extends WizardPage implements SelectionListener { setPreview(mValues.activityValues.getTemplateName()); } - private void setPreview(String template) { + private void setPreview(String templateName) { Image oldImage = mPreviewImage; mPreviewImage = null; String title = ""; String description = ""; - Document doc = TemplateHandler.getMetadataDocument(template); - if (doc != null) { - Element root = doc.getDocumentElement(); - String thumb = root.getAttribute(ATTR_THUMB); + TemplateMetadata template = TemplateHandler.getTemplate(templateName); + if (template != null) { + String thumb = template.getThumbnailPath(); if (thumb != null && !thumb.isEmpty()) { - String filePath = TemplateHandler.getTemplatePath(template) + '/' + thumb; + String filePath = TemplateHandler.getTemplatePath(templateName) + '/' + thumb; InputStream input = AdtPlugin.readEmbeddedFileAsStream(filePath); if (input != null) { try { @@ -143,8 +137,8 @@ class ActivityPage extends WizardPage implements SelectionListener { } } } - title = root.getAttribute(ATTR_NAME); - description = root.getAttribute(ATTR_DESCRIPTION); + title = template.getTitle(); + description = template.getDescription(); } mHeading.setText(title); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java index 9df974f..60f7a9e 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java @@ -317,7 +317,7 @@ public class NewProjectWizard extends Wizard implements INewWizard { parameters.put(ATTR_TARGET_API, paramMap.get(ATTR_TARGET_API)); - TemplateHandler activityTemplate = activityValues.getTemplate(); + TemplateHandler activityTemplate = activityValues.getTemplateHandler(); activityTemplate.setBackupMergedFiles(false); activityTemplate.render(outputPath, parameters); List<String> filesToOpen = activityTemplate.getFilesToOpen(); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java index f89fd11..a6fdf48 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java @@ -16,10 +16,8 @@ package com.android.ide.eclipse.adt.internal.wizards.templates; import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_DEFAULT; -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_ID; 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_THUMB; import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.PREVIEW_PADDING; import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.PREVIEW_WIDTH; @@ -57,7 +55,6 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; -import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -160,16 +157,15 @@ public class NewTemplatePage extends WizardPage // Add parameters mFirst = null; - Document doc = mValues.getTemplate().getMetadataDocument(); + TemplateMetadata template = mValues.getTemplateHandler().getTemplate(); String thumb = null; - if (doc != null) { - Element root = doc.getDocumentElement(); - thumb = root.getAttribute(ATTR_THUMB); - String title = root.getAttribute(ATTR_NAME); + if (template != null) { + thumb = template.getThumbnailPath(); + String title = template.getTitle(); if (!title.isEmpty()) { setTitle(title); } - String description = root.getAttribute(ATTR_DESCRIPTION); + String description = template.getDescription(); if (!description.isEmpty()) { setDescription(description); } @@ -180,8 +176,7 @@ public class NewTemplatePage extends WizardPage seen = new HashSet<String>(); } - - List<Parameter> parameters = Parameter.getParameters(doc); + List<Parameter> parameters = template.getParameters(); mParameters = new ArrayList<Parameter>(parameters.size()); for (Parameter parameter : parameters) { Parameter.Type type = parameter.type; @@ -288,19 +283,14 @@ public class NewTemplatePage extends WizardPage int selected = 0; List<String> ids = Lists.newArrayList(); List<String> labels = Lists.newArrayList(); - List<String> thumbs = Lists.newArrayList(); for (int i = 0, n = options.size(); i < n; i++) { Element option = options.get(i); String optionId = option.getAttribute(ATTR_ID); assert optionId != null && !optionId.isEmpty() : ATTR_ID; - String optionThumb = option.getAttribute(ATTR_THUMB); String isDefault = option.getAttribute(ATTR_DEFAULT); if (isDefault != null && !isDefault.isEmpty() && Boolean.valueOf(isDefault)) { selected = i; - if (optionThumb != null && !optionThumb.isEmpty()) { - thumb = optionThumb; - } } NodeList childNodes = option.getChildNodes(); assert childNodes.getLength() == 1 && @@ -308,11 +298,9 @@ public class NewTemplatePage extends WizardPage String optionLabel = childNodes.item(0).getNodeValue().trim(); ids.add(optionId); labels.add(optionLabel); - thumbs.add(optionThumb); } combo.setData(parameter); parameter.control = combo; - combo.setData(ATTR_THUMB, thumbs.toArray(new String[thumbs.size()])); combo.setData(ATTR_ID, ids.toArray(new String[ids.size()])); assert labels.size() > 0; combo.setItems(labels.toArray(new String[labels.size()])); @@ -371,10 +359,14 @@ public class NewTemplatePage extends WizardPage } private void setPreview(String thumb) { + if (thumb == null) { + return; + } + Image oldImage = mPreviewImage; mPreviewImage = null; - byte[] data = mValues.getTemplate().readTemplateResource(thumb); + byte[] data = mValues.getTemplateHandler().readTemplateResource(thumb); if (data != null) { try { mPreviewImage = new Image(getControl().getDisplay(), @@ -546,15 +538,15 @@ public class NewTemplatePage extends WizardPage if (index != -1 && index < optionIds.length) { String optionId = optionIds[index]; editParameter(combo, optionId); - String[] thumbs = (String[]) combo.getData(ATTR_THUMB); - String thumb = thumbs[index]; - if (thumb != null && !thumb.isEmpty()) { - setPreview(thumb); - } + TemplateMetadata template = mValues.getTemplateHandler().getTemplate(); + setPreview(template.getThumbnailPath()); } } else if (source instanceof Button) { Button button = (Button) source; editParameter(button, button.getSelection()); + + TemplateMetadata template = mValues.getTemplateHandler().getTemplate(); + setPreview(template.getThumbnailPath()); } validatePage(); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java index 5fe91c5..b7ad998 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java @@ -119,8 +119,8 @@ public class NewTemplateWizard extends Wizard implements INewWizard { parameters.put(ATTR_TARGET_API, manifest.getTargetSdkVersion()); File outputPath = AdtUtils.getAbsolutePath(project).toFile(); - TemplateHandler template = mValues.getTemplate(); - template.render(outputPath, parameters); + TemplateHandler handler = mValues.getTemplateHandler(); + handler.render(outputPath, parameters); try { project.refreshLocal(DEPTH_INFINITE, new NullProgressMonitor()); @@ -128,7 +128,7 @@ public class NewTemplateWizard extends Wizard implements INewWizard { AdtPlugin.log(e, null); } - List<String> filesToOpen = template.getFilesToOpen(); + List<String> filesToOpen = handler.getFilesToOpen(); NewTemplateWizard.openFiles(project, filesToOpen, mWorkbench); return true; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java index cb32a4f..dc75a71 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java @@ -37,7 +37,7 @@ public class NewTemplateWizardState { private String mTemplateName = BLANK_ACTIVITY; /** Template handler responsible for instantiating templates and reading resources */ - private TemplateHandler mTemplate; + private TemplateHandler mTemplateHandler; /** Configured parameters, by id */ public final Map<String, Object> parameters = new HashMap<String, Object>(); @@ -78,23 +78,23 @@ public class NewTemplateWizardState { if (!templateName.equals(mTemplateName)) { mTemplateName = templateName; mTemplateLocation = null; - mTemplate = null; + mTemplateHandler = null; } } @NonNull - TemplateHandler getTemplate() { - if (mTemplate == null) { + TemplateHandler getTemplateHandler() { + if (mTemplateHandler == null) { File inputPath; if (mTemplateLocation != null) { inputPath = mTemplateLocation; } else { inputPath = new File(TemplateHandler.getTemplatePath(mTemplateName)); } - mTemplate = TemplateHandler.createFromPath(inputPath); + mTemplateHandler = TemplateHandler.createFromPath(inputPath); } - return mTemplate; + return mTemplateHandler; } // For template development/testing only @@ -102,7 +102,7 @@ public class NewTemplateWizardState { if (!file.equals(mTemplateLocation)) { mTemplateLocation = file; mTemplateName = null; - mTemplate = null; + mTemplateHandler = null; } } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java index 1fad0e1..0b8b952 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java @@ -21,7 +21,6 @@ import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHan import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_ID; 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_SUGGEST; -import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.TAG_PARAMETER; import com.android.annotations.NonNull; import com.android.annotations.Nullable; @@ -37,13 +36,9 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.dialogs.IInputValidator; import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.swt.widgets.Control; -import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import java.util.ArrayList; import java.util.EnumSet; -import java.util.List; import java.util.Locale; /** @@ -142,24 +137,7 @@ class Parameter { } } - /** The type of parameter. Must be one of - * <ul> - * <li> string - * <li> id - * <li> class - * <li> boolean - * <li> package - * <li> apiLevel - * <li> enum (must contain option children) - * <li> Resource types: - * <ul> - * <li> layout - * <li> <i>more to come</i> - * </ul> - * </ul> - * <p> - * TODO: Switch to an enum - */ + /** The type of parameter */ @NonNull public final Type type; @@ -346,16 +324,4 @@ class Parameter { return mValidator; } - - @NonNull - static List<Parameter> getParameters(@NonNull Document document) { - NodeList parameters = document.getElementsByTagName(TAG_PARAMETER); - List<Parameter> list = new ArrayList<Parameter>(parameters.getLength()); - for (int index = 0, max = parameters.getLength(); index < max; index++) { - Element element = (Element) parameters.item(index); - list.add(new Parameter(element)); - } - - return list; - } }
\ No newline at end of file diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java index 8864502..dc0c898 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java @@ -117,6 +117,8 @@ class TemplateHandler { static final String TAG_COPY = "copy"; //$NON-NLS-1$ static final String TAG_INSTANTIATE = "instantiate"; //$NON-NLS-1$ static final String TAG_OPEN = "open"; //$NON-NLS-1$ + static final String TAG_THUMB = "thumb"; //$NON-NLS-1$ + static final String TAG_THUMBS = "thumbs"; //$NON-NLS-1$ static final String ATTR_VALUE = "value"; //$NON-NLS-1$ static final String ATTR_DEFAULT = "default"; //$NON-NLS-1$ static final String ATTR_SUGGEST = "suggest"; //$NON-NLS-1$ @@ -129,7 +131,6 @@ class TemplateHandler { static final String ATTR_TO = "to"; //$NON-NLS-1$ static final String ATTR_FROM = "from"; //$NON-NLS-1$ static final String ATTR_CONSTRAINTS = "constraints";//$NON-NLS-1$ - static final String ATTR_THUMB = "thumb"; //$NON-NLS-1$ /** Default padding to apply in wizards around the thumbnail preview images */ static final int PREVIEW_PADDING = 10; @@ -161,6 +162,11 @@ class TemplateHandler { */ private boolean mBackupMergedFiles = true; + /** + * Template metadata + */ + private TemplateMetadata mTemplate; + /** Creates a new {@link TemplateHandler} for the given root path */ static TemplateHandler createFromPath(File rootPath) { return new TemplateHandler(rootPath); @@ -222,25 +228,38 @@ class TemplateHandler { } @Nullable - public Document getMetadataDocument() { - String xml = readTemplateTextResource(TEMPLATE_XML); - if (xml != null) { - return DomUtilities.parseDocument(xml, true); - } else { - return null; + public TemplateMetadata getTemplate() { + if (mTemplate == null) { + String xml = readTemplateTextResource(TEMPLATE_XML); + if (xml != null) { + Document doc = DomUtilities.parseDocument(xml, true); + if (doc != null && doc.getDocumentElement() != null) { + mTemplate = new TemplateMetadata(doc); + } + } } + + return mTemplate; } - public static Document getMetadataDocument(String templateName) { + @Nullable + public static TemplateMetadata getTemplate(String templateName) { String relative = getTemplatePath(templateName) + '/' +TEMPLATE_XML; String xml = AdtPlugin.readEmbeddedTextFile(relative); - return DomUtilities.parseDocument(xml, true); + Document doc = DomUtilities.parseDocument(xml, true); + if (doc != null && doc.getDocumentElement() != null) { + return new TemplateMetadata(doc); + } + + return null; } + @NonNull public static String getTemplatePath(String templateName) { return TEMPLATE_PREFIX + templateName; } + @NonNull public String getResourcePath(String templateName) { return new File(mRootPath.getPath(), templateName).getPath(); } 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 0000000..eac818a --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateMetadata.java @@ -0,0 +1,145 @@ +/* + * 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.TemplateHandler.ATTR_DESCRIPTION; +import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_NAME; +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 com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.ide.eclipse.adt.AdtPlugin; + +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.HashMap; +import java.util.List; +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; + + 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(element); + mParameters.add(parameter); + if (parameter.id != null) { + mParameterMap.put(parameter.id, parameter); + } + } + } + + @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; + } + + @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 list of available parameters */ + @NonNull + List<Parameter> getParameters() { + return mParameters; + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template.xml b/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template.xml index 6294592..302e2cc 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template.xml +++ b/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template.xml @@ -1,8 +1,7 @@ <?xml version="1.0"?> <template name="New Blank Activity" - description="Creates a new blank activity, with optional inner navigation." - thumb="template_blank_activity.png"> + description="Creates a new blank activity, with optional inner navigation."> <category value="Activities" /> @@ -30,11 +29,11 @@ type="enum" default="none" help="The type of navigation to use for the activity" > - <option id="none" default="true" thumb="template_blank_activity.png">None</option> - <option id="tabs" thumb="template_blank_activity_tabs.png">Tabs</option> - <option id="tabs_pager" thumb="template_blank_activity_tabs_pager.png">Tabs + Swipe</option> - <option id="pager_strip" thumb="template_blank_activity_pager.png">Swipe Views + Title Strip</option> - <option id="dropdown" thumb="template_blank_activity_dropdown.png">Dropdown</option> + <option id="none" default="true">None</option> + <option id="tabs">Tabs</option> + <option id="tabs_pager">Tabs + Swipe</option> + <option id="pager_strip">Swipe Views + Title Strip</option> + <option id="dropdown">Dropdown</option> </parameter> <parameter @@ -52,6 +51,18 @@ constraints="package" default="com.mycompany.myapp" /> + <!-- 128x128 thumbnails relative to template.xml --> + <thumbs> + <!-- default thumbnail is required --> + <thumb>template_blank_activity.png</thumb> + <!-- attributes act as selectors based on chosen parameters --> + <thumb navType="none">template_blank_activity.png</thumb> + <thumb navType="tabs">template_blank_activity_tabs.png</thumb> + <thumb navType="tabs_pager">template_blank_activity_tabs_pager.png</thumb> + <thumb navType="pager_strip">template_blank_activity_pager.png</thumb> + <thumb navType="dropdown">template_blank_activity_dropdown.png</thumb> + </thumbs> + <globals file="globals.xml.ftl" /> <execute file="recipe.xml.ftl" /> diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template.xml b/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template.xml index bc01747..0eed682 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template.xml +++ b/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template.xml @@ -1,8 +1,11 @@ <?xml version="1.0"?> <template name="New Master/Detail Flow" - description="Creates a new master/detail flow, which is two columns on tablets, and one column on smaller screens. This creates a master fragment, detail fragment, and two activities." - thumb="template_master_detail.png"> + description="Creates a new master/detail flow, which is two columns on tablets, and one column on smaller screens. This creates a master fragment, detail fragment, and two activities."> + + <thumbs> + <thumb>template_master_detail.png</thumb> + </thumbs> <category value="Flows" /> diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template.xml b/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template.xml index 60f5363..84ba6c7 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template.xml +++ b/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template.xml @@ -1,8 +1,11 @@ <?xml version="1.0"?> <template name="New Android Application" - description="Creates a new Android application with an activity." - thumb="template_new_project.png">> + description="Creates a new Android application with an activity."> + + <thumbs> + <thumb>template_new_project.png</thumb> + </thumbs> <category value="Applications" /> diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml index c1d43ae..f5a809f 100644 --- a/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml @@ -127,5 +127,11 @@ class="com.android.ide.eclipse.ddms.preferences.LogCatPreferencePage" id="com.android.ide.eclipse.ddms.preferences.LogCatPreferencePage" name="%page.name.LogCat"/> + <page + category="com.android.ide.eclipse.ddms.preferences.LogCatPreferencePage" + class="com.android.ide.eclipse.ddms.preferences.LogCatColorsPage" + id="com.android.ide.eclipse.ddms.preferences.LogCatColorsPage" + name="Colors"> + </page> </extension> </plugin> diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/LogCatColorsPage.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/LogCatColorsPage.java new file mode 100644 index 0000000..675a51c --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/LogCatColorsPage.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 + * + * 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.ddms.preferences; + +import com.android.ddmuilib.logcat.LogCatPanel; +import com.android.ide.eclipse.ddms.DdmsPlugin; + +import org.eclipse.jface.preference.ColorFieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +public class LogCatColorsPage extends FieldEditorPreferencePage + implements IWorkbenchPreferencePage { + public LogCatColorsPage() { + super(GRID); + setPreferenceStore(DdmsPlugin.getDefault().getPreferenceStore()); + } + + @Override + public void init(IWorkbench workbench) { + } + + @Override + protected void createFieldEditors() { + // colors preference for different log levels + ColorFieldEditor cfe = new ColorFieldEditor(LogCatPanel.VERBOSE_COLOR_PREFKEY, + "Verbose Log Message Color", getFieldEditorParent()); + addField(cfe); + + cfe = new ColorFieldEditor(LogCatPanel.DEBUG_COLOR_PREFKEY, "Debug Log Message Color", + getFieldEditorParent()); + addField(cfe); + + cfe = new ColorFieldEditor(LogCatPanel.INFO_COLOR_PREFKEY, "Info Log Message Color", + getFieldEditorParent()); + addField(cfe); + + cfe = new ColorFieldEditor(LogCatPanel.WARN_COLOR_PREFKEY, "Warning Log Message Color", + getFieldEditorParent()); + addField(cfe); + + cfe = new ColorFieldEditor(LogCatPanel.ERROR_COLOR_PREFKEY, "Error Log Message Color", + getFieldEditorParent()); + addField(cfe); + + cfe = new ColorFieldEditor(LogCatPanel.ASSERT_COLOR_PREFKEY, "Assert Log Message Color", + getFieldEditorParent()); + addField(cfe); + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/LogCatPreferencePage.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/LogCatPreferencePage.java index 9971e18..a0c5450 100644 --- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/LogCatPreferencePage.java +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/LogCatPreferencePage.java @@ -30,6 +30,9 @@ import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.FontFieldEditor; import org.eclipse.jface.preference.IntegerFieldEditor; import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IPerspectiveDescriptor; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; @@ -62,18 +65,27 @@ public class LogCatPreferencePage extends FieldEditorPreferencePage implements Messages.LogCatPreferencePage_MaxMessages, getFieldEditorParent()); addField(mMaxMessages); + createHorizontalSeparator(); + if (InstallDetails.isAdtInstalled()) { createAdtSpecificFieldEditors(); } } + private void createHorizontalSeparator() { + Label l = new Label(getFieldEditorParent(), SWT.SEPARATOR | SWT.HORIZONTAL); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 3; + l.setLayoutData(gd); + } + private void createAdtSpecificFieldEditors() { mSwitchPerspective = new BooleanFieldEditor(PreferenceInitializer.ATTR_SWITCH_PERSPECTIVE, Messages.LogCatPreferencePage_Switch_Perspective, getFieldEditorParent()); addField(mSwitchPerspective); IPerspectiveDescriptor[] perspectiveDescriptors = PlatformUI.getWorkbench().getPerspectiveRegistry().getPerspectives(); - String[][] perspectives; + String[][] perspectives = new String[0][0]; if (perspectiveDescriptors.length > 0) { perspectives = new String[perspectiveDescriptors.length][2]; for (int i = 0; i < perspectiveDescriptors.length; i++) { @@ -81,8 +93,6 @@ public class LogCatPreferencePage extends FieldEditorPreferencePage implements perspectives[i][0] = perspective.getLabel(); perspectives[i][1] = perspective.getId(); } - } else { - perspectives = new String[0][0]; } mWhichPerspective = new ComboFieldEditor(PreferenceInitializer.ATTR_PERSPECTIVE_ID, Messages.LogCatPreferencePage_Switch_To, perspectives, getFieldEditorParent()); @@ -90,6 +100,8 @@ public class LogCatPreferencePage extends FieldEditorPreferencePage implements .getBoolean(PreferenceInitializer.ATTR_SWITCH_PERSPECTIVE), getFieldEditorParent()); addField(mWhichPerspective); + createHorizontalSeparator(); + mAutoMonitorLogcat = new BooleanFieldEditor(LogCatMonitor.AUTO_MONITOR_PREFKEY, Messages.LogCatPreferencePage_AutoMonitorLogcat, getFieldEditorParent()); diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java index 3f7d20e..c6e60cb 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/AndroidContentAssistTest.java @@ -25,13 +25,10 @@ import static com.android.sdklib.SdkConstants.FD_RES; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.editors.animator.AnimationContentAssist; -import com.android.ide.eclipse.adt.internal.editors.animator.AnimationEditorDelegate; import com.android.ide.eclipse.adt.internal.editors.color.ColorContentAssist; -import com.android.ide.eclipse.adt.internal.editors.color.ColorEditorDelegate; +import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor; import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableContentAssist; -import com.android.ide.eclipse.adt.internal.editors.drawable.DrawableEditorDelegate; import com.android.ide.eclipse.adt.internal.editors.layout.LayoutContentAssist; -import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.AdtProjectTest; import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestContentAssist; import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestEditor; @@ -773,34 +770,34 @@ public class AndroidContentAssistTest extends AdtProjectTest { private void checkLayoutCompletion(String name, String caretLocation) throws Exception { IFile file = getLayoutFile(getProject(), name); - IDE.setDefaultEditor(file, LayoutEditorDelegate.LEGACY_EDITOR_ID); + IDE.setDefaultEditor(file, CommonXmlEditor.ID); checkCompletion(name, file, caretLocation, new LayoutContentAssist()); } private void checkColorCompletion(String name, String caretLocation) throws Exception { IFile file = getTestDataFile(getProject(), name, FD_RES + "/" + FD_RES_COLOR + "/" + name); - IDE.setDefaultEditor(file, ColorEditorDelegate.LEGACY_EDITOR_ID); + IDE.setDefaultEditor(file, CommonXmlEditor.ID); checkCompletion(name, file, caretLocation, new ColorContentAssist()); } private void checkAnimCompletion(String name, String caretLocation) throws Exception { IFile file = getTestDataFile(getProject(), name, FD_RES + "/" + FD_RES_ANIM + "/" + name); - IDE.setDefaultEditor(file, AnimationEditorDelegate.LEGACY_EDITOR_ID); + IDE.setDefaultEditor(file, CommonXmlEditor.ID); checkCompletion(name, file, caretLocation, new AnimationContentAssist()); } private void checkAnimatorCompletion(String name, String caretLocation) throws Exception { IFile file = getTestDataFile(getProject(), name, FD_RES + "/" + FD_RES_ANIMATOR + "/" + name); - IDE.setDefaultEditor(file, AnimationEditorDelegate.LEGACY_EDITOR_ID); + IDE.setDefaultEditor(file, CommonXmlEditor.ID); checkCompletion(name, file, caretLocation, new AnimationContentAssist()); } private void checkDrawableCompletion(String name, String caretLocation) throws Exception { IFile file = getTestDataFile(getProject(), name, FD_RES + "/" + FD_RES_DRAWABLE + "/" + name); - IDE.setDefaultEditor(file, DrawableEditorDelegate.LEGACY_EDITOR_ID); + IDE.setDefaultEditor(file, CommonXmlEditor.ID); checkCompletion(name, file, caretLocation, new DrawableContentAssist()); } @@ -851,6 +848,8 @@ public class AndroidContentAssistTest extends AdtProjectTest { proposals = new ICompletionProposal[0]; } + editor.getEditorSite().getPage().closeAllEditors(false); + return proposals; } diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/HyperlinksTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/HyperlinksTest.java index 0d42357..a54376d 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/HyperlinksTest.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/HyperlinksTest.java @@ -19,8 +19,6 @@ import static com.android.sdklib.SdkConstants.FD_SOURCES; import com.android.ide.common.resources.ResourceFile; import com.android.ide.eclipse.adt.AdtUtils; -import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; -import com.android.ide.eclipse.adt.internal.editors.Hyperlinks; import com.android.ide.eclipse.adt.internal.editors.Hyperlinks.ResourceLink; import com.android.ide.eclipse.adt.internal.editors.Hyperlinks.XmlResolver; import com.android.ide.eclipse.adt.internal.editors.layout.refactoring.AdtProjectTest; @@ -180,6 +178,12 @@ public class HyperlinksTest extends AdtProjectTest { "class=\"com.and^roid.eclipse.tests.TestFragment\""); } + public void testNavigate15() throws Exception { + // Check navigating to a theme resource + checkXmlNavigation("navigation1.xml", "res/layout/navigation1.xml", + "?android:attr/alert^DialogStyle"); + } + // Left to test: // onClick handling // class attributes diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java index a816cff..8ddfff5 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/AdtProjectTest.java @@ -411,7 +411,6 @@ public class AdtProjectTest extends SdkTestCase { } } - boolean showBeforeWindow = firstDelta >= beforeLines.length - lastDelta; boolean showAfterWindow = firstDelta >= afterLines.length - lastDelta; diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion55.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion55.txt index 17cf984..8f6cd32 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion55.txt +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion55.txt @@ -12,5 +12,5 @@ android:startOffset : Delay in milliseconds before the animation runs, once star android:repeatCount : Defines how many times the animation should repeat. [integer, enum] android:repeatMode : Defines the animation behavior when it reaches the end and the repeat count is greater than 0 or infinite. [enum] android:zAdjustment : Allows for an adjustment of the Z ordering of the content being animated for the duration of the animation. [enum] -android:background : Special background behind animation. [reference, color] +android:background : Special background behind animation. [color, reference] android:detachWallpaper : Special option for window animations: if this window is on top of a wallpaper, don't animate the wallpaper with it. [boolean] diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion56.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion56.txt index 837a6cc..5110e73 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion56.txt +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/anim1-expected-completion56.txt @@ -10,5 +10,5 @@ android:startOffset : Delay in milliseconds before the animation runs, once star android:repeatCount : Defines how many times the animation should repeat. [integer, enum] android:repeatMode : Defines the animation behavior when it reaches the end and the repeat count is greater than 0 or infinite. [enum] android:zAdjustment : Allows for an adjustment of the Z ordering of the content being animated for the duration of the animation. [enum] -android:background : Special background behind animation. [reference, color] +android:background : Special background behind animation. [color, reference] android:detachWallpaper : Special option for window animations: if this window is on top of a wallpaper, don't animate the wallpaper with it. [boolean] diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion61.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion61.txt index 1ba8a62..b298ac0 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion61.txt +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/animator1-expected-completion61.txt @@ -11,7 +11,6 @@ Code completion in animator1.xml for android:interpolator="^@android:anim/bounce @android: @+id/ @anim/ -@animator/ @color/ @drawable/ @id/ diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/broken1-expected-completion20.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/broken1-expected-completion20.txt index c5aa1a0..063dc8c 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/broken1-expected-completion20.txt +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/broken1-expected-completion20.txt @@ -1,2 +1,2 @@ Code completion in broken1.xml for android:textColorHigh^: -android:textColorHighlight : Color of the text selection highlight. [reference, color] +android:textColorHighlight : Color of the text selection highlight. [color, reference] diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion39.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion39.txt index ac18c6d..281d7a0 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion39.txt +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion1-expected-completion39.txt @@ -3,15 +3,15 @@ style : A reference to a custom style [reference] android:bufferType : Determines the minimum type that getText() will return. [enum] android:text : Text to display. [string] android:hint : Hint text to display when the text is empty. [string] -android:textColor : Text color. [reference, color] -android:textColorHighlight : Color of the text selection highlight. [reference, color] -android:textColorHint : Color of the hint text. [reference, color] +android:textColor : Text color. [color, reference] +android:textColorHighlight : Color of the text selection highlight. [color, reference] +android:textColorHint : Color of the hint text. [color, reference] android:textAppearance : Base text color, typeface, size, and style. [reference] android:textSize : Size of the text. [dimension] android:textScaleX : Sets the horizontal scaling factor for the text. [float] android:typeface : Typeface (normal, sans, serif, monospace) for the text. [enum] android:textStyle : Style (bold, italic, bolditalic) for the text. [flag] -android:textColorLink : Text color for links. [reference, color] +android:textColorLink : Text color for links. [color, reference] android:cursorVisible : Makes the cursor visible (the default) or invisible. [boolean] android:maxLines : Makes the TextView be at most this many lines tall. [integer] android:maxHeight : Makes the TextView be at most this many pixels tall. [dimension] @@ -48,10 +48,10 @@ android:autoText : If set, specifies that this TextView has a textual input meth android:editable : If set, specifies that this TextView has an input method. * Deprecated: Use inputType instead. [boolean] android:freezesText : If set, the text view will include its current complete text inside of its frozen icicle in addition to meta-data such as the current cursor position. [boolean] android:ellipsize : If set, causes words that are longer than the view is wide to be ellipsized instead of broken in the middle. [enum] -android:drawableTop : The drawable to be drawn above the text. [reference, color] -android:drawableBottom : The drawable to be drawn below the text. [reference, color] -android:drawableLeft : The drawable to be drawn to the left of the text. [reference, color] -android:drawableRight : The drawable to be drawn to the right of the text. [reference, color] +android:drawableTop : The drawable to be drawn above the text. [color, reference] +android:drawableBottom : The drawable to be drawn below the text. [color, reference] +android:drawableLeft : The drawable to be drawn to the left of the text. [color, reference] +android:drawableRight : The drawable to be drawn to the right of the text. [color, reference] android:drawablePadding : The padding between the drawables and the text. [dimension] android:lineSpacingExtra : Extra spacing between lines of text. [dimension] android:lineSpacingMultiplier : Extra spacing between lines of text, as a multiplier. [float] @@ -75,7 +75,7 @@ android:id : Supply an identifier name for this view, to later retrieve it with android:tag : Supply a tag for this view containing a String, to be retrieved later with View.getTag() or searched for with View.findViewWithTag() . [string] android:scrollX : The initial horizontal scroll offset, in pixels. [dimension] android:scrollY : The initial vertical scroll offset, in pixels. [dimension] -android:background : A drawable to use as the background. [reference, color] +android:background : A drawable to use as the background. [color, reference] android:padding : Sets the padding, in pixels, of all four edges. [dimension] android:paddingLeft : Sets the padding, in pixels, of the left edge; see padding. [dimension] android:paddingTop : Sets the padding, in pixels, of the top edge; see padding. [dimension] diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion5-expected-completion40.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion5-expected-completion40.txt index 138e225..be3d8d5 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion5-expected-completion40.txt +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completion5-expected-completion40.txt @@ -3,15 +3,15 @@ style : A reference to a custom style [reference] android:bufferType : Determines the minimum type that getText() will return. [enum] android:text : Text to display. [string] android:hint : Hint text to display when the text is empty. [string] -android:textColor : Text color. [reference, color] -android:textColorHighlight : Color of the text selection highlight. [reference, color] -android:textColorHint : Color of the hint text. [reference, color] +android:textColor : Text color. [color, reference] +android:textColorHighlight : Color of the text selection highlight. [color, reference] +android:textColorHint : Color of the hint text. [color, reference] android:textAppearance : Base text color, typeface, size, and style. [reference] android:textSize : Size of the text. [dimension] android:textScaleX : Sets the horizontal scaling factor for the text. [float] android:typeface : Typeface (normal, sans, serif, monospace) for the text. [enum] android:textStyle : Style (bold, italic, bolditalic) for the text. [flag] -android:textColorLink : Text color for links. [reference, color] +android:textColorLink : Text color for links. [color, reference] android:cursorVisible : Makes the cursor visible (the default) or invisible. [boolean] android:maxLines : Makes the TextView be at most this many lines tall. [integer] android:maxHeight : Makes the TextView be at most this many pixels tall. [dimension] @@ -48,10 +48,10 @@ android:autoText : If set, specifies that this TextView has a textual input meth android:editable : If set, specifies that this TextView has an input method. * Deprecated: Use inputType instead. [boolean] android:freezesText : If set, the text view will include its current complete text inside of its frozen icicle in addition to meta-data such as the current cursor position. [boolean] android:ellipsize : If set, causes words that are longer than the view is wide to be ellipsized instead of broken in the middle. [enum] -android:drawableTop : The drawable to be drawn above the text. [reference, color] -android:drawableBottom : The drawable to be drawn below the text. [reference, color] -android:drawableLeft : The drawable to be drawn to the left of the text. [reference, color] -android:drawableRight : The drawable to be drawn to the right of the text. [reference, color] +android:drawableTop : The drawable to be drawn above the text. [color, reference] +android:drawableBottom : The drawable to be drawn below the text. [color, reference] +android:drawableLeft : The drawable to be drawn to the left of the text. [color, reference] +android:drawableRight : The drawable to be drawn to the right of the text. [color, reference] android:drawablePadding : The padding between the drawables and the text. [dimension] android:lineSpacingExtra : Extra spacing between lines of text. [dimension] android:lineSpacingMultiplier : Extra spacing between lines of text, as a multiplier. [float] @@ -75,7 +75,7 @@ android:id : Supply an identifier name for this view, to later retrieve it with android:tag : Supply a tag for this view containing a String, to be retrieved later with View.getTag() or searched for with View.findViewWithTag() . [string] android:scrollX : The initial horizontal scroll offset, in pixels. [dimension] android:scrollY : The initial vertical scroll offset, in pixels. [dimension] -android:background : A drawable to use as the background. [reference, color] +android:background : A drawable to use as the background. [color, reference] android:padding : Sets the padding, in pixels, of all four edges. [dimension] android:paddingLeft : Sets the padding, in pixels, of the left edge; see padding. [dimension] android:paddingTop : Sets the padding, in pixels, of the top edge; see padding. [dimension] diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt index 3592e04..7e27fa6 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/completionvalues1-expected-completion32.txt @@ -14,7 +14,7 @@ android:animationResolution : Timeout between frames of animation in millisecond android:autoLink : Controls whether links such as urls and email addresses are automatically found and converted to clickable links. [flag] android:autoStart : When true, automatically start animating [boolean] android:autoText : If set, specifies that this TextView has a textual input method and automatically corrects some common spelling errors. * Deprecated: Use inputType instead. [boolean] -android:background : A drawable to use as the background. [reference, color] +android:background : A drawable to use as the background. [color, reference] android:baseline : The offset of the baseline within this view. [dimension] android:baselineAlignBottom : If true, the image view will be baseline aligned with based on its bottom edge. [boolean] android:baselineAligned : When set to false, prevents the layout from aligning its children's baselines. [boolean] @@ -28,7 +28,7 @@ android:capitalize : If set, specifies that this TextView has a textual input me android:checkMark : Drawable used for the check mark graphic. [reference] android:checked : Indicates the initial checked state of this button. [boolean] android:checkedButton : The id of the child radio button that should be checked by default within this radio group. [integer] -android:childDivider : Drawable or color that is used as a divider for children. [reference, color] +android:childDivider : Drawable or color that is used as a divider for children. [color, reference] android:childIndicator : Indicator shown beside the child View. [reference] android:childIndicatorLeft : The left bound for a child's indicator. [dimension] android:childIndicatorRight : The right bound for a child's indicator. [dimension] @@ -55,16 +55,16 @@ android:divider : Drawable to use as a vertical divider between buttons. android:dividerHeight : Height of the divider. [dimension] android:dividerPadding : Size of padding on either end of a divider. [dimension] android:drawSelectorOnTop : When set to true, the selector will be drawn over the selected item. [boolean] -android:drawableBottom : The drawable to be drawn below the text. [reference, color] -android:drawableLeft : The drawable to be drawn to the left of the text. [reference, color] +android:drawableBottom : The drawable to be drawn below the text. [color, reference] +android:drawableLeft : The drawable to be drawn to the left of the text. [color, reference] android:drawablePadding : The padding between the drawables and the text. [dimension] -android:drawableRight : The drawable to be drawn to the right of the text. [reference, color] -android:drawableTop : The drawable to be drawn above the text. [reference, color] +android:drawableRight : The drawable to be drawn to the right of the text. [color, reference] +android:drawableTop : The drawable to be drawn above the text. [color, reference] android:drawingCacheQuality : Defines the quality of translucent drawing caches. [enum] android:dropDownAnchor : View to anchor the auto-complete dropdown to. [reference] android:dropDownHeight : Specifies the basic height of the dropdown. [dimension, enum] android:dropDownHorizontalOffset : Horizontal offset from the spinner widget for positioning the dropdown in spinnerMode="dropdown". [dimension] -android:dropDownSelector : List selector to use for spinnerMode="dropdown" display. [reference, color] +android:dropDownSelector : List selector to use for spinnerMode="dropdown" display. [color, reference] android:dropDownVerticalOffset : Vertical offset from the spinner widget for positioning the dropdown in spinnerMode="dropdown". [dimension] android:dropDownWidth : Width of the dropdown in spinnerMode="dropdown". [dimension, enum] android:duplicateParentState : When this attribute is set to true, the view gets its drawable state (focused, pressed, etc.) from its direct parent rather than from itself. [boolean] @@ -92,9 +92,9 @@ android:flingable : @hide Whether the number picker supports fligning. [boolean android:flipInterval : [integer] android:focusable : Boolean that controls whether a view can take focus. [boolean] android:focusableInTouchMode : Boolean that controls whether a view can take focus while in touch mode. [boolean] -android:focusedMonthDateColor : The color for the dates of the selected month. [reference, color] +android:focusedMonthDateColor : The color for the dates of the selected month. [color, reference] android:footerDividersEnabled : When set to false, the ListView will not draw the divider before each footer view. [boolean] -android:foreground : Defines the drawable to draw over the content. [reference, color] +android:foreground : Defines the drawable to draw over the content. [color, reference] android:foregroundGravity : Defines the gravity to apply to the foreground drawable. [flag] android:foregroundInsidePadding : Defines whether the foreground drawable should be drawn inside the padding. [boolean] android:format : Format string: if specified, the Chronometer will display this string, with the first "%s" replaced by the current timer value in "MM:SS" or "H:MM:SS" form. [string] @@ -144,7 +144,7 @@ android:lineSpacingExtra : Extra spacing between lines of text. [dimension] android:lineSpacingMultiplier : Extra spacing between lines of text, as a multiplier. [float] android:lines : Makes the TextView be exactly this many lines tall. [integer] android:linksClickable : If set to false, keeps the movement method from being set to the link movement method even if autoLink causes links to be found. [boolean] -android:listSelector : Drawable used to indicate the currently selected item in the list. [reference, color] +android:listSelector : Drawable used to indicate the currently selected item in the list. [color, reference] android:longClickable : Defines whether this view reacts to long click events. [boolean] android:loopViews : Defines whether the animator loops to the first view once it has reached the end of the list. [boolean] android:marqueeRepeatLimit : The number of times to repeat the marquee animation. [integer, enum] @@ -175,8 +175,8 @@ android:numeric : If set, specifies that this TextView has a numeric input metho android:onClick : Name of the method in this View's context to invoke when the view is clicked. [string] android:orientation : Should the layout be a column or a row? Use "horizontal" for a row, "vertical" for a column. [enum] android:outAnimation : Identifier for the animation to use when a view is hidden. [reference] -android:overScrollFooter : Drawable to draw below list content. [reference, color] -android:overScrollHeader : Drawable to draw above list content. [reference, color] +android:overScrollFooter : Drawable to draw below list content. [color, reference] +android:overScrollHeader : Drawable to draw above list content. [color, reference] android:overScrollMode : Defines over-scrolling behavior. [enum] android:padding : Sets the padding, in pixels, of all four edges. [dimension] android:paddingBottom : Sets the padding, in pixels, of the bottom edge; see padding. [dimension] @@ -186,7 +186,7 @@ android:paddingTop : Sets the padding, in pixels, of the top edge; see padding. android:password : Whether the characters of the field are displayed as password dots instead of themselves. * Deprecated: Use inputType instead. [boolean] android:persistentDrawingCache : Defines the persistence of the drawing cache. [flag] android:phoneNumber : If set, specifies that this TextView has a phone number input method. * Deprecated: Use inputType instead. [boolean] -android:popupBackground : Background drawable to use for the dropdown in spinnerMode="dropdown". [reference, color] +android:popupBackground : Background drawable to use for the dropdown in spinnerMode="dropdown". [color, reference] android:popupPromptView : Reference to a layout to use for displaying a prompt in the dropdown for spinnerMode="dropdown". [reference] android:privateImeOptions : An addition content type description to supply to the input method attached to the text view, which is private to the implementation of the input method. [string] android:progress : Defines the default progress value, between 0 and max. [integer] @@ -220,7 +220,7 @@ android:scrollingCache : When set to true, the list uses a drawing cache during android:secondaryProgress : Defines the secondary progress value, between 0 and max. [integer] android:selectAllOnFocus : If the text is selectable, select it all when the view takes focus instead of moving the cursor to the start or end. [boolean] android:selectedDateVerticalBar : Drawable for the vertical bar shown at the beggining and at the end of a selected date. [reference] -android:selectedWeekBackgroundColor : The background color for the selected week. [reference, color] +android:selectedWeekBackgroundColor : The background color for the selected week. [color, reference] android:selectionDivider : @hide The divider for making the selection area. [reference] android:selectionDividerHeight : @hide The height of the selection divider. [dimension] android:shadowColor : Place a shadow of the specified color behind the text. [color] @@ -233,13 +233,13 @@ android:shownWeekCount : The number of weeks to be shown. [integer] android:shrinkColumns : The zero-based index of the columns to shrink. [string] android:singleLine : Constrains the text to a single horizontally scrolling line instead of letting it wrap onto multiple lines, and advances focus instead of inserting a newline when you press the enter key. * Deprecated: This attribute is deprecated and is replaced by the textMultiLine flag in the inputType attribute. Use caution when altering existing layouts, as the default value of singeLine is false (multi-line mode), but if you specify any value for inputType, the default is single-line mode. (If both singleLine and inputType attributes are found, the inputType flags will override the value of singleLine.). [boolean] android:smoothScrollbar : When set to true, the list will use a more refined calculation method based on the pixels height of the items visible on screen. [boolean] -android:solidColor : @hide Color for the solid color background if such for optimized rendering. [reference, color] +android:solidColor : @hide Color for the solid color background if such for optimized rendering. [color, reference] android:soundEffectsEnabled : Boolean that controls whether a view should have sound effects enabled for events such as clicking and touching. [boolean] android:spacing : [dimension] android:spinnerMode : Display mode for spinner options. [enum] android:spinnersShown : Whether the spinners are shown. [boolean] android:splitMotionEvents : Sets whether this ViewGroup should split MotionEvents to separate child views during touch event dispatch. [boolean] -android:src : Sets a drawable as the content of this ImageView. [reference, color] +android:src : Sets a drawable as the content of this ImageView. [color, reference] android:stackFromBottom : Used by ListView and GridView to stack their content from the bottom. [boolean] android:startYear : The first year (inclusive), for example "1940". [integer] android:stepSize : The step size of the rating. [float] @@ -253,10 +253,10 @@ android:tabStripRight : Drawable used to draw the right part of the strip undern android:tag : Supply a tag for the top-level view containing a String, to be retrieved later with View.getTag() or searched for with View.findViewWithTag() . [string] android:text : Text to display. [string] android:textAppearance : Base text color, typeface, size, and style. [reference] -android:textColor : Text color. [reference, color] -android:textColorHighlight : Color of the text selection highlight. [reference, color] -android:textColorHint : Color of the hint text. [reference, color] -android:textColorLink : Text color for links. [reference, color] +android:textColor : Text color. [color, reference] +android:textColorHighlight : Color of the text selection highlight. [color, reference] +android:textColorHint : Color of the hint text. [color, reference] +android:textColorLink : Text color for links. [color, reference] android:textCursorDrawable : Reference to a drawable that will be drawn under the insertion cursor. [reference] android:textEditNoPasteWindowLayout : Variation of textEditPasteWindowLayout displayed when the clipboard is empty. [reference] android:textEditPasteWindowLayout : The layout of the view that is displayed on top of the cursor to paste inside a TextEdit field. [reference] @@ -283,13 +283,13 @@ android:translationX : translation in x of the view. [dimension] android:translationY : translation in y of the view. [dimension] android:typeface : Typeface (normal, sans, serif, monospace) for the text. [enum] android:uncertainGestureColor : Color used to draw the user's strokes until we are sure it's a gesture. [color] -android:unfocusedMonthDateColor : The color for the dates of an unfocused month. [reference, color] +android:unfocusedMonthDateColor : The color for the dates of an unfocused month. [color, reference] android:unselectedAlpha : Sets the alpha on the items that are not selected. [float] android:verticalScrollbarPosition : Determines which side the vertical scroll bar should be placed on. [enum] android:verticalSpacing : Defines the default vertical spacing between rows. [dimension] android:visibility : Controls the initial visibility of the view. [enum] android:weekDayTextAppearance : The text appearance for the week day abbreviation of the calendar header. [reference] -android:weekNumberColor : The color for the week numbers. [reference, color] -android:weekSeparatorLineColor : The color for the sepatator line between weeks. [reference, color] +android:weekNumberColor : The color for the week numbers. [color, reference] +android:weekSeparatorLineColor : The color for the sepatator line between weeks. [color, reference] android:weightSum : Defines the maximum weight sum. [float] android:width : Makes the TextView be exactly this many pixels wide. [dimension] diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion47.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion47.txt index edf4892..c7f495b 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion47.txt +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion47.txt @@ -1,5 +1,4 @@ Code completion in drawable1.xml for ^<layer-list: -<animated-rotate /> <animation-list /> : Drawable used to render several animated frames. <bitmap /> : Drawable used to draw bitmaps. <clip /> diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion50.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion50.txt index 90eab10..d05bc76 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion50.txt +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/drawable1-expected-completion50.txt @@ -1,5 +1,4 @@ Code completion in drawable1.xml for <item >^</item>: -<animated-rotate /> <animation-list /> : Drawable used to render several animated frames. <bitmap /> : Drawable used to draw bitmaps. <clip /> diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt index 382011e..627ff01 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/manifest-expected-completion69.txt @@ -1,19 +1,19 @@ Code completion in manifest.xml for <uses-sdk android:minSdkVersion="^11" />: -AOSP -14 : Android 4.0.1 -13 : Android 3.2 -12 : Android 3.1 -11 : Android 3.0 -10 -9 : Android 2.3 -8 : Android 2.2 -7 -6 -5 : Android 2.0 -4 : Android 1.6 -3 : Android 1.5 -2 : Android 1.1 -1 +15 : API 15: Android 4.0.3 (IceCreamSandwich) +14 : API 14: Android 4.0 (IceCreamSandwich) +13 : API 13: Android 3.2 (Honeycomb) +12 : API 12: Android 3.1 (Honeycomb) +11 : API 11: Android 3.0 (Honeycomb) +10 : API 10: Android 2.3.3 (Gingerbread) +9 : API 9: Android 2.3 (Gingerbread) +8 : API 8: Android 2.2 (Froyo) +7 : API 7: Android 2.1 (Eclair) +6 : API 6: Android 2.0.1 (Eclair) +5 : API 5: Android 2.0 (Eclair) +4 : API 4: Android 1.6 (Donut) +3 : API 3: Android 1.5 (Cupcake) +2 : API 2: Android 1.1 +1 : API 1: Android 1.0 @string/ @android: @+id/ diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/navigation1-expected-navigate15.txt b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/navigation1-expected-navigate15.txt new file mode 100644 index 0000000..e36c5f3 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/navigation1-expected-navigate15.txt @@ -0,0 +1,7 @@ +Go To Declaration in navigation1.xml for ?android:attr/alert^DialogStyle: +Open Declaration in values/attrs.xml : [?android:attr/alertDialogStyle] + data/res/values/attrs.xml + + +After open, the selected text is: + <attr name="alertDialogStyle" format="reference" />^ diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/navigation1.xml b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/navigation1.xml index 9c175fc..e7ac4bc 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/navigation1.xml +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/testdata/navigation1.xml @@ -13,4 +13,5 @@ <EditText android:text="@android:string/ok" </EditText> + <EditText android:text="?android:attr/alertDialogStyle" /> </LinearLayout> |