blob: 56ed5ca43d30acc9dd9b58701d3c4417cfe5a9a9 [file] [log] [blame]
/*
* Copyright (C) 2015 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.tools.idea.uibuilder.property;
import com.android.tools.idea.uibuilder.LayoutTestCase;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class NlPropertiesTest extends LayoutTestCase {
private static final String[] VIEW_ATTRS = {"id", "padding", "visibility", "textAlignment", "translationZ", "elevation", "style"};
private static final String[] TEXTVIEW_ATTRS = {"text", "hint", "textColor", "textSize"};
private static final String[] FRAMELAYOUT_ATTRS = {"layout_gravity"};
private static final String[] GRIDLAYOUT_ATTRS = {"layout_rowSpan", "layout_column"};
private static final String[] LINEARLAYOUT_ATTRS = {"layout_weight"};
private static final String[] RELATIVELAYOUT_ATTRS = {"layout_toLeftOf", "layout_above", "layout_alignTop"};
public void testViewAttributes() {
@Language("XML")
String source = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<View xmlns:android=\"http://schemas.android.com/apk/res/android\" />";
XmlFile xmlFile = (XmlFile)myFixture.addFileToProject("res/layout/layout.xml", source);
String tag = "View";
List<NlProperty> properties = NlProperties.getInstance().getProperties(MockNlComponent.create(xmlFile.getRootTag()));
assertTrue(properties.size() > 120); // at least 124 attributes (view + layouts) are available as of API 22
// check that some of the View's attributes are there..
assertPresent(tag, properties, VIEW_ATTRS);
// check that non-existent properties haven't been added
assertAbsent(tag, properties, TEXTVIEW_ATTRS);
// Views that don't have a parent layout have all the layout attributes available to them..
assertPresent(tag, properties, RELATIVELAYOUT_ATTRS);
assertPresent(tag, properties, GRIDLAYOUT_ATTRS);
assertPresent(tag, properties, FRAMELAYOUT_ATTRS);
}
public void testViewInRelativeLayout() {
@Language("XML")
String source = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\" >" +
" <TextView />" +
"</RelativeLayout>";
XmlFile xmlFile = (XmlFile)myFixture.addFileToProject("res/layout/layout.xml", source);
String tag = "TextView";
XmlTag[] subTags = xmlFile.getRootTag().getSubTags();
assertEquals(1, subTags.length);
List<NlProperty> properties = NlProperties.getInstance().getProperties(MockNlComponent.create(subTags[0]));
assertTrue(properties.size() > 180); // at least 190 attributes are available as of API 22
// A textview should have all of its attributes and the parent class's (View) attributes
assertPresent(tag, properties, TEXTVIEW_ATTRS);
assertPresent(tag, properties, VIEW_ATTRS);
// Since it is embedded inside a relative layout, it should only have relative layout's layout attributes
assertPresent(tag, properties, RELATIVELAYOUT_ATTRS);
assertAbsent(tag, properties, GRIDLAYOUT_ATTRS);
assertAbsent(tag, properties, FRAMELAYOUT_ATTRS);
}
public void testCustomViewAttributes() {
XmlFile xmlFile = setupCustomViewProject();
String tag = "p1.p2.PieChart";
XmlTag[] subTags = xmlFile.getRootTag().getSubTags();
assertEquals(1, subTags.length);
List<NlProperty> properties = NlProperties.getInstance().getProperties(MockNlComponent.create(subTags[0]));
assertTrue("# of properties lesser than expected: " + properties.size(), properties.size() > 90);
assertPresent(tag, properties, VIEW_ATTRS);
assertPresent(tag, properties, LINEARLAYOUT_ATTRS);
assertAbsent(tag, properties, TEXTVIEW_ATTRS);
}
public void testPropertyNames() {
XmlFile xmlFile = setupCustomViewProject();
XmlTag[] subTags = xmlFile.getRootTag().getSubTags();
assertEquals(1, subTags.length);
List<NlProperty> properties = NlProperties.getInstance().getProperties(MockNlComponent.create(subTags[0]));
NlProperty p = getPropertyByName(properties, "id");
assertNotNull(p);
assertEquals("id", p.getName());
assertEquals("@android:id", p.getTooltipText());
p = getPropertyByName(properties, "legend");
assertNotNull(p);
assertEquals("legend", p.getName());
assertEquals("legend", p.getTooltipText());
}
private XmlFile setupCustomViewProject() {
@Language("XML")
String layoutSrc = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\" >" +
" <p1.p2.PieChart />" +
"</LinearLayout>";
@Language("XML")
String attrsSrc = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<resources>\n" +
" <declare-styleable name=\"PieChart\">\n" +
" <attr name=\"legend\" format=\"boolean\" />\n" +
" <attr name=\"labelPosition\" format=\"enum\">\n" +
" <enum name=\"left\" value=\"0\"/>\n" +
" <enum name=\"right\" value=\"1\"/>\n" +
" </attr>\n" +
" </declare-styleable>\n" +
"</resources>";
@Language("JAVA")
String javaSrc = "package p1.p2;\n" +
"\n" +
"import android.content.Context;\n" +
"import android.view.View;\n" +
"\n" +
"public class PieChart extends View {\n" +
" public PieChart(Context context) {\n" +
" super(context);\n" +
" }\n" +
"}\n";
XmlFile xmlFile = (XmlFile)myFixture.addFileToProject("res/layout/layout.xml", layoutSrc);
myFixture.addFileToProject("res/values/attrs.xml", attrsSrc);
myFixture.addFileToProject("src/p1/p2/PieChart.java", javaSrc);
return xmlFile;
}
public void testAppCompatIssues() {
@Language("XML")
String source = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\" >" +
" <TextView />" +
"</RelativeLayout>";
XmlFile xmlFile = (XmlFile)myFixture.addFileToProject("res/layout/layout.xml", source);
@Language("XML")
String attrsSrc = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<resources>\n" +
" <declare-styleable name=\"View\">\n" +
" <attr name=\"android:focusable\" />\n" +
" <attr name=\"theme\" format=\"reference\" />\n" +
" <attr name=\"android:theme\" />\n" +
" <attr name=\"custom\" />\n" +
" </declare-styleable>\n" +
"</resources>";
myFixture.addFileToProject("res/values/attrs.xml", attrsSrc);
XmlTag[] subTags = xmlFile.getRootTag().getSubTags();
assertEquals(1, subTags.length);
List<NlProperty> properties = NlProperties.getInstance().getProperties(MockNlComponent.create(subTags[0]));
assertTrue(properties.size() > 180); // at least 190 attributes are available as of API 22
// The attrs.xml in appcompat-22.0.0 includes android:focusable, theme and android:theme.
// The android:focusable refers to the platform attribute, and hence should not be duplicated..
assertPresent("TextView", properties, "focusable", "theme", "custom");
assertAbsent("TextView", properties, "android:focusable", "android:theme");
}
@Nullable
public static NlProperty getPropertyByName(@NotNull List<NlProperty> properties, @NotNull String name) {
for (NlProperty property : properties) {
if (name.equals(property.getName())) {
return property;
}
}
return null;
}
private static void assertPresent(String tag, List<NlProperty> properties, String... names) {
for (String n : names) {
assertNotNull("Missing attribute " + n + " for " + tag, getPropertyByName(properties, n));
}
}
private static void assertAbsent(String tag, List<NlProperty> properties, String... names) {
for (String n : names) {
assertNull("Attribute " + n + " not applicable for a " + tag, getPropertyByName(properties, n));
}
}
}