aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditorDelegate.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java24
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java134
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiDocumentNode.java51
5 files changed, 180 insertions, 43 deletions
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 cae0259..b20d190 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
@@ -383,7 +383,9 @@ public class LayoutEditorDelegate extends CommonXmlDelegate
@Override
public void done(IJobChangeEvent event) {
LayoutActionBar bar = getGraphicalEditor().getLayoutActionBar();
- bar.updateErrorIndicator();
+ if (!bar.isDisposed()) {
+ bar.updateErrorIndicator();
+ }
}
});
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java
index 8725fa4..2da7678 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java
@@ -86,6 +86,30 @@ public class DomUtilities {
}
/**
+ * Returns all elements below the given node (which can be a document,
+ * element, etc). This will include the node itself, if it is an element.
+ *
+ * @param node the node to search from
+ * @return all elements in the subtree formed by the node parameter
+ */
+ public static List<Element> getAllElements(Node node) {
+ List<Element> elements = new ArrayList<Element>(64);
+ addElements(node, elements);
+ return elements;
+ }
+
+ private static void addElements(Node node, List<Element> elements) {
+ if (node instanceof Element) {
+ elements.add((Element) node);
+ }
+
+ NodeList childNodes = node.getChildNodes();
+ for (int i = 0, n = childNodes.getLength(); i < n; i++) {
+ addElements(childNodes.item(i), elements);
+ }
+ }
+
+ /**
* Returns the depth of the given node (with the document node having depth 0,
* and the document element having depth 1)
*
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
index 8504bf9..236d5fd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
@@ -17,13 +17,22 @@
package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
import static com.android.ide.common.layout.LayoutConstants.ANDROID_STRING_PREFIX;
+import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI;
+import static com.android.ide.common.layout.LayoutConstants.ATTR_ID;
+import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_HEIGHT;
+import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_WIDTH;
+import static com.android.ide.common.layout.LayoutConstants.GRID_LAYOUT;
import static com.android.ide.common.layout.LayoutConstants.SCROLL_VIEW;
import static com.android.ide.common.layout.LayoutConstants.STRING_PREFIX;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_FILL_PARENT;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_MATCH_PARENT;
+import static com.android.ide.common.layout.LayoutConstants.VALUE_WRAP_CONTENT;
import static com.android.ide.eclipse.adt.AdtConstants.ANDROID_PKG;
import static com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor.viewNeedsPackage;
import static com.android.sdklib.SdkConstants.FD_GEN_SOURCES;
import com.android.ide.common.api.Rect;
+import com.android.ide.common.layout.BaseLayoutRule;
import com.android.ide.common.rendering.LayoutLibrary;
import com.android.ide.common.rendering.StaticRenderSession;
import com.android.ide.common.rendering.api.Capability;
@@ -164,7 +173,7 @@ import java.util.Set;
* @since GLE2
*/
public class GraphicalEditorPart extends EditorPart
- implements IPageImageProvider, ISelectionListener, INullSelectionListener {
+ implements IPageImageProvider, INullSelectionListener {
/*
* Useful notes:
@@ -1628,15 +1637,15 @@ public class GraphicalEditorPart extends EditorPart
addTypoSuggestions(clazz, getAndroidViewClassNames(project), false);
addActionLink(mErrorLabel,
- ActionLinkStyleRange.LINK_FIX_BUILD_PATH, "Fix Build Path", clazz, null);
+ ActionLinkStyleRange.LINK_FIX_BUILD_PATH, "Fix Build Path", clazz);
addText(mErrorLabel, ", ");
addActionLink(mErrorLabel,
- ActionLinkStyleRange.LINK_EDIT_XML, "Edit XML", clazz, null);
+ ActionLinkStyleRange.LINK_EDIT_XML, "Edit XML", clazz);
if (clazz.indexOf('.') != -1) {
// Add "Create Class" link, but only for custom views
addText(mErrorLabel, ", ");
addActionLink(mErrorLabel,
- ActionLinkStyleRange.LINK_CREATE_CLASS, "Create Class", clazz, null);
+ ActionLinkStyleRange.LINK_CREATE_CLASS, "Create Class", clazz);
}
addText(mErrorLabel, ")\n");
}
@@ -1651,10 +1660,10 @@ public class GraphicalEditorPart extends EditorPart
addText(mErrorLabel, "- ");
addText(mErrorLabel, " (");
addActionLink(mErrorLabel,
- ActionLinkStyleRange.LINK_OPEN_CLASS, "Open Class", clazz, null);
+ ActionLinkStyleRange.LINK_OPEN_CLASS, "Open Class", clazz);
addText(mErrorLabel, ", ");
addActionLink(mErrorLabel,
- ActionLinkStyleRange.LINK_SHOW_LOG, "Show Error Log", clazz, null);
+ ActionLinkStyleRange.LINK_SHOW_LOG, "Show Error Log", clazz);
addText(mErrorLabel, ")\n");
if (!(clazz.startsWith("android.") || //$NON-NLS-1$
@@ -1705,9 +1714,8 @@ public class GraphicalEditorPart extends EditorPart
// Only show full package name if class name
// is the same
labelClass),
- actual,
- viewNeedsPackage(suggested) ? suggested : suggestedBase
- );
+ actual,
+ viewNeedsPackage(suggested) ? suggested : suggestedBase);
addText(mErrorLabel, ", ");
}
}
@@ -1803,6 +1811,21 @@ public class GraphicalEditorPart extends EditorPart
addBoldText(mErrorLabel, message);
}
+ if (logger.seenTag(RenderLogger.TAG_MISSING_DIMENSION)) {
+ List<UiElementNode> elements = UiDocumentNode.getAllElements(getModel());
+ for (UiElementNode element : elements) {
+ String width = element.getAttributeValue(ATTR_LAYOUT_WIDTH);
+ if (width == null || width.length() == 0) {
+ addSetAttributeLink(element, ATTR_LAYOUT_WIDTH);
+ }
+
+ String height = element.getAttributeValue(ATTR_LAYOUT_HEIGHT);
+ if (height == null || height.length() == 0) {
+ addSetAttributeLink(element, ATTR_LAYOUT_HEIGHT);
+ }
+ }
+ }
+
String problems = logger.getProblems(false /*includeFidelityWarnings*/);
addText(mErrorLabel, problems);
@@ -1814,7 +1837,7 @@ public class GraphicalEditorPart extends EditorPart
addText(mErrorLabel, warning + ' ');
addActionLink(mErrorLabel,
ActionLinkStyleRange.IGNORE_FIDELITY_WARNING,
- "(Ignore for this session)\n", warning, null);
+ "(Ignore for this session)\n", warning);
}
}
@@ -1824,6 +1847,44 @@ public class GraphicalEditorPart extends EditorPart
}
}
+ /** Appends an action link to set the given attribute on the given value */
+ private void addSetAttributeLink(UiElementNode element, String attribute) {
+ if (element.getXmlNode().getNodeName().equals(GRID_LAYOUT)) {
+ // GridLayout does not require a layout_width or layout_height to be defined
+ return;
+ }
+
+ String fill = VALUE_FILL_PARENT;
+ // See whether we should offer match_parent instead of fill_parent
+ Sdk currentSdk = Sdk.getCurrent();
+ if (currentSdk != null) {
+ IAndroidTarget target = currentSdk.getTarget(getProject());
+ if (target.getVersion().getApiLevel() >= 8) {
+ fill = VALUE_MATCH_PARENT;
+ }
+ }
+
+ String id = element.getAttributeValue(ATTR_ID);
+ if (id == null || id.length() == 0) {
+ id = '<' + element.getXmlNode().getNodeName() + '>';
+ } else {
+ id = BaseLayoutRule.stripIdPrefix(id);
+ }
+
+ addText(mErrorLabel, String.format("\"%1$s\" does not set the required %2$s attribute:\n",
+ id, attribute));
+ addText(mErrorLabel, " (1) ");
+ addActionLink(mErrorLabel,
+ ActionLinkStyleRange.SET_ATTRIBUTE,
+ String.format("Set to \"%1$s\"", VALUE_WRAP_CONTENT),
+ element, attribute, VALUE_WRAP_CONTENT);
+ addText(mErrorLabel, "\n (2) ");
+ addActionLink(mErrorLabel,
+ ActionLinkStyleRange.SET_ATTRIBUTE,
+ String.format("Set to \"%1$s\"\n", fill),
+ element, attribute, fill);
+ }
+
/** Appends the given text as a bold string in the given text widget */
private void addBoldText(StyledText styledText, String text) {
String s = styledText.getText();
@@ -1844,12 +1905,12 @@ public class GraphicalEditorPart extends EditorPart
* action, corresponding to the value fields in {@link ActionLinkStyleRange}.
*/
private void addActionLink(StyledText styledText, int action, String label,
- String data1, String data2) {
+ Object... data) {
String s = styledText.getText();
int start = (s == null ? 0 : s.length());
styledText.append(label);
- StyleRange sr = new ActionLinkStyleRange(action, data1, data2);
+ StyleRange sr = new ActionLinkStyleRange(action, data);
sr.start = start;
sr.length = label.length();
sr.fontStyle = SWT.NORMAL;
@@ -1997,26 +2058,25 @@ public class GraphicalEditorPart extends EditorPart
private static final int LINK_CHANGE_CLASS_TO = 6;
/** Ignore the given fidelity warning */
private static final int IGNORE_FIDELITY_WARNING = 7;
+ /** Set an attribute on the given XML element to a given value */
+ private static final int SET_ATTRIBUTE = 8;
- /** Client data 1 - usually the class name */
- private final String mData1;
- /** Client data 2 - such as the suggested new name */
- private final String mData2;
+ /** Client data: the contents depend on the specific action */
+ private final Object[] mData;
/** The action to be taken when the link is clicked */
private final int mAction;
- private ActionLinkStyleRange(int action, String data1, String data2) {
+ private ActionLinkStyleRange(int action, Object... data) {
super();
mAction = action;
- mData1 = data1;
- mData2 = data2;
+ mData = data;
}
/** Performs the click action */
public void onClick() {
switch (mAction) {
case LINK_CREATE_CLASS:
- createNewClass(mData1);
+ createNewClass((String) mData[0]);
break;
case LINK_EDIT_XML:
mEditorDelegate.getEditor().setActivePage(AndroidXmlEditor.TEXT_EDITOR_ID);
@@ -2029,7 +2089,7 @@ public class GraphicalEditorPart extends EditorPart
getProject(), id, null, null).open();
break;
case LINK_OPEN_CLASS:
- AdtPlugin.openJavaClass(getProject(), mData1);
+ AdtPlugin.openJavaClass(getProject(), (String) mData[0]);
break;
case LINK_SHOW_LOG:
IWorkbench workbench = PlatformUI.getWorkbench();
@@ -2042,7 +2102,7 @@ public class GraphicalEditorPart extends EditorPart
}
break;
case LINK_CHANGE_CLASS_TO:
- // Change class reference of mData1 to mData2
+ // Change class reference of mData[0] to mData[1]
// TODO: run under undo lock
MultiTextEdit edits = new MultiTextEdit();
ISourceViewer textViewer =
@@ -2052,8 +2112,8 @@ public class GraphicalEditorPart extends EditorPart
int index = 0;
// Replace <old with <new and </old with </new
String prefix = "<"; //$NON-NLS-1$
- String find = prefix + mData1;
- String replaceWith = prefix + mData2;
+ String find = prefix + mData[0];
+ String replaceWith = prefix + mData[1];
while (true) {
index = xml.indexOf(find, index);
if (index == -1) {
@@ -2064,8 +2124,8 @@ public class GraphicalEditorPart extends EditorPart
}
index = 0;
prefix = "</"; //$NON-NLS-1$
- find = prefix + mData1;
- replaceWith = prefix + mData2;
+ find = prefix + mData[0];
+ replaceWith = prefix + mData[1];
while (true) {
index = xml.indexOf(find, index);
if (index == -1) {
@@ -2078,8 +2138,8 @@ public class GraphicalEditorPart extends EditorPart
index = 0;
prefix = "\""; //$NON-NLS-1$
String suffix = "\""; //$NON-NLS-1$
- find = prefix + mData1 + suffix;
- replaceWith = prefix + mData2 + suffix;
+ find = prefix + mData[0] + suffix;
+ replaceWith = prefix + mData[1] + suffix;
while (true) {
index = xml.indexOf(find, index);
if (index == -1) {
@@ -2097,10 +2157,26 @@ public class GraphicalEditorPart extends EditorPart
}
break;
case IGNORE_FIDELITY_WARNING:
- RenderLogger.ignoreFidelityWarning(mData1);
+ RenderLogger.ignoreFidelityWarning((String) mData[0]);
recomputeLayout();
break;
+ case SET_ATTRIBUTE: {
+ final UiElementNode element = (UiElementNode) mData[0];
+ final String attribute = (String) mData[1];
+ final String value = (String) mData[2];
+ mEditorDelegate.getEditor().wrapUndoEditXmlModel(
+ String.format("Set \"%1$s\" to \"%2$s\"", attribute, value),
+ new Runnable() {
+ @Override
+ public void run() {
+ element.setAttributeValue(attribute, ANDROID_URI, value, true);
+ element.commitDirtyAttributesToXml();
+ }
+ });
+ break;
+ }
default:
+ assert false : mAction;
break;
}
}
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 83bd95f..74bc4f5 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
@@ -31,6 +31,8 @@ import java.util.Set;
* single summary at the end
*/
class RenderLogger extends LayoutLog {
+ static final String TAG_MISSING_DIMENSION = "missing.dimension"; //$NON-NLS-1$
+
private final String mName;
private List<String> mFidelityWarnings;
private List<String> mWarnings;
@@ -143,6 +145,14 @@ class RenderLogger extends LayoutLog {
public void warning(String tag, String message, Object data) {
String description = describe(message);
AdtPlugin.log(IStatus.WARNING, "%1$s: %2$s", mName, description);
+
+ 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;
+ }
+ }
+
addWarning(tag, description);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiDocumentNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiDocumentNode.java
index beac5e1..1a85ea6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiDocumentNode.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiDocumentNode.java
@@ -22,6 +22,9 @@ import com.android.ide.eclipse.adt.internal.editors.uimodel.IUiUpdateListener.Ui
import org.w3c.dom.Document;
import org.w3c.dom.Node;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Represents an XML document node that can be modified by the user interface in the XML editor.
* <p/>
@@ -29,10 +32,10 @@ import org.w3c.dom.Node;
* {@link DocumentDescriptor}.
*/
public class UiDocumentNode extends UiElementNode {
-
+
/**
* Creates a new {@link UiDocumentNode} described by a given {@link DocumentDescriptor}.
- *
+ *
* @param documentDescriptor The {@link DocumentDescriptor} for the XML node. Cannot be null.
*/
public UiDocumentNode(DocumentDescriptor documentDescriptor) {
@@ -43,17 +46,17 @@ public class UiDocumentNode extends UiElementNode {
* Computes a short string describing the UI node suitable for tree views.
* Uses the element's attribute "android:name" if present, or the "android:label" one
* followed by the element's name.
- *
+ *
* @return A short string describing the UI node suitable for tree views.
*/
@Override
public String getShortDescription() {
return "Document"; //$NON-NLS-1$
}
-
+
/**
* Computes a "breadcrumb trail" description for this node.
- *
+ *
* @param include_root Whether to include the root (e.g. "Manifest") or not. Has no effect
* when called on the root node itself.
* @return The "breadcrumb trail" description for this node.
@@ -62,7 +65,7 @@ public class UiDocumentNode extends UiElementNode {
public String getBreadcrumbTrailDescription(boolean include_root) {
return "Document"; //$NON-NLS-1$
}
-
+
/**
* This method throws an exception when attempted to assign a parent, since XML documents
* cannot have a parent. It is OK to assign null.
@@ -78,13 +81,13 @@ public class UiDocumentNode extends UiElementNode {
/**
* Populate this element node with all values from the given XML node.
- *
+ *
* This fails if the given XML node has a different element name -- it won't change the
* type of this ui node.
- *
+ *
* This method can be both used for populating values the first time and updating values
* after the XML model changed.
- *
+ *
* @param xml_node The XML node to mirror
* @return Returns true if the XML structure has changed (nodes added, removed or replaced)
*/
@@ -98,13 +101,13 @@ public class UiDocumentNode extends UiElementNode {
}
return structure_changed;
}
-
+
/**
* This method throws an exception if there is no underlying XML document.
* <p/>
* XML documents cannot be created per se -- they are a by-product of the StructuredEditor
* XML parser.
- *
+ *
* @return The current value of getXmlDocument().
*/
@Override
@@ -123,13 +126,35 @@ public class UiDocumentNode extends UiElementNode {
* <p/>
* XML documents cannot be deleted per se -- they are a by-product of the StructuredEditor
* XML parser.
- *
- * @return The removed node or null if it didn't exist in the firtst place.
+ *
+ * @return The removed node or null if it didn't exist in the first place.
*/
@Override
public Node deleteXmlNode() {
// DEBUG. Change to log warning.
throw new UnsupportedOperationException("Documents cannot be deleted"); //$NON-NLS-1$
}
+
+ /**
+ * Returns all elements in this document.
+ *
+ * @param document the document
+ * @return all elements in the document
+ */
+ public static List<UiElementNode> getAllElements(UiDocumentNode document) {
+ List<UiElementNode> elements = new ArrayList<UiElementNode>(64);
+ for (UiElementNode child : document.getUiChildren()) {
+ addElements(child, elements);
+ }
+ return elements;
+ }
+
+ private static void addElements(UiElementNode node, List<UiElementNode> elements) {
+ elements.add(node);
+
+ for (UiElementNode child : node.getUiChildren()) {
+ addElements(child, elements);
+ }
+ }
}