diff options
7 files changed, 341 insertions, 28 deletions
diff --git a/eclipse/dictionary.txt b/eclipse/dictionary.txt index b3c0fba..a010809 100644 --- a/eclipse/dictionary.txt +++ b/eclipse/dictionary.txt @@ -30,6 +30,7 @@ configurability coords ddms debuggable +dedent deprecated deselect deselects 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 1e745b3..5ffc17e 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 @@ -39,7 +39,9 @@ import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorInput; @@ -67,6 +69,7 @@ import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; import org.eclipse.wst.sse.ui.StructuredTextEditor; +import org.eclipse.wst.sse.ui.internal.StructuredTextViewer; import org.eclipse.wst.xml.core.internal.document.NodeContainer; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; import org.w3c.dom.Document; @@ -87,7 +90,7 @@ import java.net.URL; public abstract class AndroidXmlEditor extends FormEditor implements IResourceChangeListener { /** Preference name for the current page of this file */ - private static final String PREF_CURRENT_PAGE = "_current_page"; + private static final String PREF_CURRENT_PAGE = "_current_page"; // $NON-NLS-1$ /** Id string used to create the Android SDK browser */ private static String BROWSER_ID = "android"; // $NON-NLS-1$ @@ -946,7 +949,7 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh * Get the XML text directly from the editor. * * @param xmlNode The node whose XML text we want to obtain. - * @return The XML representation of the {@link Node}. + * @return The XML representation of the {@link Node}, or null if there was an error. */ public String getXmlText(Node xmlNode) { String data = null; @@ -975,6 +978,135 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh } /** + * Formats the text around the given caret range, using the current Eclipse + * XML formatter settings. + * + * @param begin The starting offset of the range to be reformatted. + * @param end The ending offset of the range to be reformatted. + */ + public void reformatRegion(int begin, int end) { + ISourceViewer textViewer = getStructuredSourceViewer(); + + // Clamp text range to valid offsets. + IDocument document = textViewer.getDocument(); + int documentLength = document.getLength(); + end = Math.min(end, documentLength); + begin = Math.min(begin, end); + + // It turns out the XML formatter does *NOT* format things correctly if you + // select just a region of text. You *MUST* also include the leading whitespace + // on the line, or it will dedent all the content to column 0. Therefore, + // we must figure out the offset of the start of the line that contains the + // beginning of the tag. + try { + IRegion lineInformation = document.getLineInformationOfOffset(begin); + if (lineInformation != null) { + int lineBegin = lineInformation.getOffset(); + if (lineBegin != begin) { + begin = lineBegin; + } else if (begin > 0) { + // Trick #2: It turns out that, if an XML element starts in column 0, + // then the XML formatter will NOT indent it (even if its parent is + // indented). If you on the other hand include the end of the previous + // line (the newline), THEN the formatter also correctly inserts the + // element. Therefore, we adjust the beginning range to include the + // previous line (if we are not already in column 0 of the first line) + // in the case where the element starts the line. + begin--; + } + } + } catch (BadLocationException e) { + // This cannot happen because we already clamped the offsets + AdtPlugin.log(e, e.toString()); // $NON-NLS-1$ + } + + if (textViewer instanceof StructuredTextViewer) { + StructuredTextViewer structuredTextViewer = (StructuredTextViewer) textViewer; + int operation = ISourceViewer.FORMAT; + boolean canFormat = structuredTextViewer.canDoOperation(operation); + if (canFormat) { + StyledText textWidget = textViewer.getTextWidget(); + textWidget.setSelection(begin, end); + structuredTextViewer.doOperation(operation); + } + } + } + + /** + * Formats the XML region corresponding to the given node. + * + * @param node The node to be formatted. + */ + public void reformatNode(Node node) { + if (mIsCreatingPage) { + return; + } + + if (node instanceof IndexedRegion) { + IndexedRegion region = (IndexedRegion) node; + int begin = region.getStartOffset(); + int end = region.getEndOffset(); + reformatRegion(begin, end); + } + } + + /** + * Formats the XML document according to the user's XML formatting settings. + */ + public void reformatDocument() { + ISourceViewer textViewer = getStructuredSourceViewer(); + if (textViewer instanceof StructuredTextViewer) { + StructuredTextViewer structuredTextViewer = (StructuredTextViewer) textViewer; + int operation = StructuredTextViewer.FORMAT_DOCUMENT; + boolean canFormat = structuredTextViewer.canDoOperation(operation); + if (canFormat) { + structuredTextViewer.doOperation(operation); + } + } + } + + /** + * Returns the indentation String of the given node. + * + * @param xmlNode The node whose indentation we want. + * @return The indent-string of the given node, or "" if the indentation for some reason could + * not be computed. + */ + public String getIndent(Node xmlNode) { + assert xmlNode.getNodeType() == Node.ELEMENT_NODE; + + if (xmlNode instanceof IndexedRegion) { + IndexedRegion region = (IndexedRegion)xmlNode; + IDocument document = getStructuredSourceViewer().getDocument(); + int startOffset = region.getStartOffset(); + try { + IRegion lineInformation = document.getLineInformationOfOffset(startOffset); + if (lineInformation != null) { + int lineBegin = lineInformation.getOffset(); + if (lineBegin != startOffset) { + String prefix = document.get(lineBegin, startOffset - lineBegin); + + // It's possible that the tag whose indentation we seek is not + // at the beginning of the line. In that case we'll just return + // the indentation of the line itself. + for (int i = 0; i < prefix.length(); i++) { + if (!Character.isWhitespace(prefix.charAt(i))) { + return prefix.substring(0, i); + } + } + + return prefix; + } + } + } catch (BadLocationException e) { + AdtPlugin.log(e, "Could not obtain indentation"); // $NON-NLS-1$ + } + } + + return ""; // $NON-NLS-1$ + } + + /** * Listen to changes in the underlying XML model in the structured editor. */ private class XmlModelStateListener implements IModelStateListener { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditor.java index c23a4d4..180c329 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditor.java @@ -543,7 +543,7 @@ public class LayoutEditor extends AndroidXmlEditor implements IShowEditorInput, if (layoutDesc != null) { DocumentDescriptor docDesc = layoutDesc.getDescriptor(); if (docDesc != null) { - desc = internalFindFqcnViewDescritor(fqcn, docDesc.getChildren(), null); + desc = internalFindFqcnViewDescriptor(fqcn, docDesc.getChildren(), null); } } } @@ -567,7 +567,7 @@ public class LayoutEditor extends AndroidXmlEditor implements IShowEditorInput, * necessary since the view descriptor hierarchy is cyclic. * @return Either a matching {@link ViewElementDescriptor} or null. */ - private ViewElementDescriptor internalFindFqcnViewDescritor(String fqcn, + private ViewElementDescriptor internalFindFqcnViewDescriptor(String fqcn, ElementDescriptor[] descriptors, Set<ElementDescriptor> visited) { if (visited == null) { @@ -587,7 +587,7 @@ public class LayoutEditor extends AndroidXmlEditor implements IShowEditorInput, // Visit its children ViewElementDescriptor vd = - internalFindFqcnViewDescritor(fqcn, desc.getChildren(), visited); + internalFindFqcnViewDescriptor(fqcn, desc.getChildren(), visited); if (vd != null) { return vd; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java index 530be06..5f5af7c 100755 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java @@ -198,7 +198,7 @@ public class NodeProxy implements INode { checkEditOK(); // Find the descriptor for this FQCN - ViewElementDescriptor vd = getFqcnViewDescritor(viewFqcn); + ViewElementDescriptor vd = getFqcnViewDescriptor(viewFqcn); if (vd == null) { warnPrintf("Can't create a new %s element", viewFqcn); return null; @@ -230,7 +230,7 @@ public class NodeProxy implements INode { checkEditOK(); // Find the descriptor for this FQCN - ViewElementDescriptor vd = getFqcnViewDescritor(viewFqcn); + ViewElementDescriptor vd = getFqcnViewDescriptor(viewFqcn); if (vd == null) { warnPrintf("Can't create a new %s element", viewFqcn); return null; @@ -364,7 +364,7 @@ public class NodeProxy implements INode { * (which shouldn't really happen since at this point the SDK should be fully loaded and * isn't reloading, or we wouldn't be here editing XML for a layout rule.) */ - private ViewElementDescriptor getFqcnViewDescritor(String fqcn) { + private ViewElementDescriptor getFqcnViewDescriptor(String fqcn) { AndroidXmlEditor editor = mNode.getEditor(); if (editor instanceof LayoutEditor) { return ((LayoutEditor) editor).getFqcnViewDescriptor(fqcn); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiElementNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiElementNode.java index 71d8e8f..121dd3f 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiElementNode.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/uimodel/UiElementNode.java @@ -30,6 +30,7 @@ import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.Android import com.android.ide.eclipse.adt.internal.editors.resources.descriptors.ResourcesDescriptors; import com.android.ide.eclipse.adt.internal.editors.uimodel.IUiUpdateListener.UiUpdateState; import com.android.ide.eclipse.adt.internal.editors.xml.descriptors.XmlDescriptors; +import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; import com.android.ide.eclipse.adt.internal.resources.AttributeInfo; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; import com.android.sdklib.SdkConstants; @@ -295,6 +296,7 @@ public class UiElementNode implements IPropertySource { * <p/> * The XML {@link Document} is initially null. The XML {@link Document} must be set only on the * UI root element node (this method takes care of that.) + * @param xmlDoc The new XML document to associate this node with. */ public void setXmlDocument(Document xmlDoc) { if (mUiParent == null) { @@ -340,6 +342,7 @@ public class UiElementNode implements IPropertySource { * <p/> * Do not use this to call getDescriptor().getAttributes(), instead call * getAttributeDescriptors() which can be overridden by derived classes. + * @return The {@link ElementDescriptor} for this node. This is never null. */ public ElementDescriptor getDescriptor() { return mDescriptor; @@ -350,6 +353,7 @@ public class UiElementNode implements IPropertySource { * <p/> * Use this instead of getDescriptor().getAttributes() -- derived classes can override * this to manipulate the attribute descriptor list depending on the current UI node. + * @return The {@link AttributeDescriptor} array for the descriptor of this node. */ public AttributeDescriptor[] getAttributeDescriptors() { return mDescriptor.getAttributes(); @@ -396,7 +400,9 @@ public class UiElementNode implements IPropertySource { } /** - * Returns The root {@link UiElementNode}. + * Returns the root {@link UiElementNode}. + * + * @return The root {@link UiElementNode}. */ public UiElementNode getUiRoot() { UiElementNode root = this; @@ -408,8 +414,10 @@ public class UiElementNode implements IPropertySource { } /** - * Returns the previous UI sibling of this UI node. - * If the node does not have a previous sibling, returns null. + * Returns the previous UI sibling of this UI node. If the node does not have a previous + * sibling, returns null. + * + * @return The previous UI sibling of this UI node, or null if not applicable. */ public UiElementNode getUiPreviousSibling() { if (mUiParent != null) { @@ -425,6 +433,8 @@ public class UiElementNode implements IPropertySource { /** * Returns the next UI sibling of this UI node. * If the node does not have a next sibling, returns null. + * + * @return The next UI sibling of this UI node, or null. */ public UiElementNode getUiNextSibling() { if (mUiParent != null) { @@ -444,6 +454,8 @@ public class UiElementNode implements IPropertySource { * Sets the {@link AndroidXmlEditor} handling this {@link UiElementNode} hierarchy. * <p/> * The editor must always be set on the root node. This method takes care of that. + * + * @param editor The editor to associate this node with. */ public void setEditor(AndroidXmlEditor editor) { if (mUiParent == null) { @@ -467,6 +479,8 @@ public class UiElementNode implements IPropertySource { /** * Returns the Android target data for the file being edited. + * + * @return The Android target data for the file being edited. */ public AndroidTargetData getAndroidTarget() { return getEditor().getTargetData(); @@ -502,6 +516,7 @@ public class UiElementNode implements IPropertySource { /** * Sets the error flag value. + * * @param errorFlag the error flag */ public final void setHasError(boolean errorFlag) { @@ -511,6 +526,9 @@ public class UiElementNode implements IPropertySource { /** * Returns whether this node, its attributes, or one of the children nodes (and attributes) * has errors. + * + * @return True if this node, its attributes, or one of the children nodes (and attributes) + * has errors. */ public final boolean hasError() { if (mHasError) { @@ -596,6 +614,8 @@ public class UiElementNode implements IPropertySource { /** * Adds a new {@link IUiUpdateListener} to the internal update listener list. + * + * @param listener The listener to add. */ public void addUpdateListener(IUiUpdateListener listener) { if (mUiUpdateListeners == null) { @@ -609,6 +629,8 @@ public class UiElementNode implements IPropertySource { /** * Removes an existing {@link IUiUpdateListener} from the internal update listener list. * Does nothing if the list is empty or the listener is not registered. + * + * @param listener The listener to remove. */ public void removeUpdateListener(IUiUpdateListener listener) { if (mUiUpdateListeners != null) { @@ -833,20 +855,81 @@ public class UiElementNode implements IPropertySource { xmlNextSibling = uiNextSibling.getXmlNode(); } - // If this is the first element we are adding into a new element, - // we need to insert a newline at the beginning too. Unless it's already - // there, which is the case for the root element created for the .xml template - // files - but this is why we use the xml node list rather than the element - // count. - if (parentXmlNode.getChildNodes().getLength() == 0) { - parentXmlNode.insertBefore(doc.createTextNode("\n"), xmlNextSibling); //$NON-NLS-1$ + Node previousTextNode = null; + if (xmlNextSibling != null) { + Node previousNode = xmlNextSibling.getPreviousSibling(); + if (previousNode != null && previousNode.getNodeType() == Node.TEXT_NODE) { + previousTextNode = previousNode; + } + } else { + Node lastChild = parentXmlNode.getLastChild(); + if (lastChild != null && lastChild.getNodeType() == Node.TEXT_NODE) { + previousTextNode = lastChild; + } } + String insertAfter = null; + + // Try to figure out the indentation node to insert. Even in auto-formatting + // we need to do this, because it turns out the XML editor's formatter does + // not do a very good job with completely botched up XML; it does a much better + // job if the new XML is already mostly well formatted. Thus, the main purpose + // of applying the real XML formatter after our own indentation attempts here is + // to make it apply its own tab-versus-spaces indentation properties, have it + // insert line breaks before attributes (if the user has configured that), etc. + + // First figure out the indentation level of the newly inserted element; + // this is either the same as the previous sibling, or if there is no sibling, + // it's the indentation of the parent plus one indentation level. + boolean isFirstChild = getUiPreviousSibling() == null + || parentXmlNode.getFirstChild() == null; + AndroidXmlEditor editor = getEditor(); + String indent; + String parentIndent = ""; //$NON-NLS-1$ + if (isFirstChild) { + indent = parentIndent = editor.getIndent(parentXmlNode); + // We need to add one level of indentation. Are we using tabs? + // Can't get to formatting settings so let's just look at the + // parent indentation and see if we can guess + if (indent.length() > 0 && indent.charAt(indent.length()-1) == '\t') { + indent = indent + '\t'; + } else { + // Not using tabs, or we can't figure it out (because parent had no + // indentation). In that case, indent with 4 spaces, as seems to + // be the Android default. + indent = indent + " "; //$NON-NLS-1$ + } + } else { + // Find out the indent of the previous sibling + indent = editor.getIndent(getUiPreviousSibling().getXmlNode()); + } + + // We want to insert the new element BEFORE the text node which precedes + // the next element, since that text node is the next element's indentation! + if (previousTextNode != null) { + xmlNextSibling = previousTextNode; + } else { + // If there's no previous text node, we are probably inside an + // empty element (<LinearLayout>|</LinearLayout>) and in that case we need + // to not only insert a newline and indentation before the new element, but + // after it as well. + insertAfter = parentIndent; + } + + // Insert indent text node before the new element + Text indentNode = doc.createTextNode("\n" + indent); //$NON-NLS-1$ + parentXmlNode.insertBefore(indentNode, xmlNextSibling); + + // Insert the element itself parentXmlNode.insertBefore(mXmlNode, xmlNextSibling); - // Insert a separator after the tag, to make it easier to read - Text sep = doc.createTextNode("\n"); //$NON-NLS-1$ - parentXmlNode.insertBefore(sep, xmlNextSibling); + // Insert a separator after the tag. We only do this when we've inserted + // a tag into an area where there was no whitespace before + // (e.g. a new child of <LinearLayout></LinearLayout>). + if (insertAfter != null) { + Text sep = doc.createTextNode("\n" + insertAfter); //$NON-NLS-1$ + parentXmlNode.insertBefore(sep, xmlNextSibling); + } // Set all initial attributes in the XML node if they are not empty. // Iterate on the descriptor list to get the desired order and then use the @@ -865,6 +948,10 @@ public class UiElementNode implements IPropertySource { } } + if (mUiParent != null) { + mUiParent.formatOnInsert(this); + } + invokeUiUpdateListeners(UiUpdateState.CREATED); return mXmlNode; } @@ -890,14 +977,18 @@ public class UiElementNode implements IPropertySource { if (xmlParent == null) { xmlParent = getXmlDocument(); } - Node nextSibling = oldXmlNode.getNextSibling(); + Node previousSibling = oldXmlNode.getPreviousSibling(); oldXmlNode = xmlParent.removeChild(oldXmlNode); - // Remove following text node if it's just blank space, to account for - // the fact what we add these when we insert nodes. - if (nextSibling != null && nextSibling.getNodeType() == Node.TEXT_NODE - && nextSibling.getNodeValue().trim().length() == 0) { - xmlParent.removeChild(nextSibling); + // We need to remove the text node BEFORE the removed element, since THAT's the + // indentation node for the removed element. + if (previousSibling != null && previousSibling.getNodeType() == Node.TEXT_NODE + && previousSibling.getNodeValue().trim().length() == 0) { + xmlParent.removeChild(previousSibling); + } + + if (mUiParent != null) { + mUiParent.formatOnDeletion(this); } invokeUiUpdateListeners(UiUpdateState.DELETED); @@ -1070,6 +1161,7 @@ public class UiElementNode implements IPropertySource { } mUiChildren.remove(uiIndex); + return true; } finally { // Tell listeners that a node has been removed. @@ -1667,4 +1759,76 @@ public class UiElementNode implements IPropertySource { }); } } + + /** Handles reformatting of the XML buffer when a given node has been inserted. + * + * @param node The node that was inserted. + */ + private void formatOnInsert(UiElementNode node) { + // Reformat parent if it's the first child (such that it for example can force + // children into their own lines.) + if (mUiChildren.size() == 1) { + reformat(); + } else { + // In theory, we should ONLY have to reformat the node itself: + // uiNode.reformat(); + // + // However, the XML formatter does not correctly handle this; in particular + // it will -dedent- a correctly indented child. Here's an example: + // + // @formatter:off + // <?xml version="1.0" encoding="utf-8"?> + // <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + // android:layout_width="fill_parent" android:layout_height="fill_parent" + // android:orientation="vertical"> + // <LinearLayout android:id="@+id/LinearLayout01" + // android:layout_width="wrap_content" android:layout_height="wrap_content"> + // <Button android:id="@+id/Button03"></Button> + // </LinearLayout> + // </LinearLayout> + // @formatter:on + // + // If we have just inserted the button inside the nested LinearLayout, and + // attempt to format it, it will incorrectly dedent the button to be flush with + // its parent. + // + // Therefore, for now, in this case, format the PARENT on insert. This means that + // siblings can be formatted as well, but that can't be helped. + + // This should be "uiNode.reformat();" instead of "reformat()" if formatting + // worked correctly: + reformat(); + } + } + + /** + * Handles reformatting of the XML buffer when a given node has been removed. + * + * @param node The node that was removed. + */ + private void formatOnDeletion(UiElementNode node) { + // Reformat parent if it's the last child removed, such that we can for example + // place the closing element back on the same line as the opening tag (if the + // user has that mode configured in the formatting options.) + if (mUiChildren.size() <= 1) { + // <= 1 instead of == 0: turns out the parent hasn't always deleted + // this child from its its children list yet. + reformat(); + } + } + + /** + * Reformats the XML corresponding to the given XML node. This will do nothing if we have + * errors, or if the user has turned off XML auto-formatting. + */ + private void reformat() { + if (mHasError || !AdtPrefs.getPrefs().getFormatXml()) { + return; + } + + AndroidXmlEditor editor = getEditor(); + if (editor != null && mXmlNode != null) { + editor.reformatNode(mXmlNode); + } + } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AdtPrefs.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AdtPrefs.java index 11210e3..de5847b 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AdtPrefs.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AdtPrefs.java @@ -46,6 +46,8 @@ public final class AdtPrefs extends AbstractPreferenceInitializer { public final static String PREFS_MONITOR_DENSITY = AdtPlugin.PLUGIN_ID + ".monitorDensity"; //$NON-NLS-1$ + public final static String PREFS_FORMAT_XML = AdtPlugin.PLUGIN_ID + ".formatXml"; //$NON-NLS-1$ + /** singleton instance */ private final static AdtPrefs sThis = new AdtPrefs(); @@ -60,6 +62,7 @@ public final class AdtPrefs extends AbstractPreferenceInitializer { private boolean mBuildForceResResfresh = false; private boolean mBuildForceErrorOnNativeLibInJar = true; + private boolean mFormatXml = false; private float mMonitorDensity = 0.f; public static enum BuildVerbosity { @@ -139,6 +142,10 @@ public final class AdtPrefs extends AbstractPreferenceInitializer { if (property == null || PREFS_MONITOR_DENSITY.equals(property)) { mMonitorDensity = mStore.getFloat(PREFS_MONITOR_DENSITY); } + + if (property == null || PREFS_FORMAT_XML.equals(property)) { + mFormatXml = mStore.getBoolean(PREFS_FORMAT_XML); + } } /** @@ -153,10 +160,14 @@ public final class AdtPrefs extends AbstractPreferenceInitializer { return mBuildVerbosity; } - public boolean getBuildForceResResfresh() { + public boolean getBuildForceResResfresh() { return mBuildForceResResfresh; } + public boolean getFormatXml() { + return mFormatXml; + } + public boolean getBuildForceErrorOnNativeLibInJar() { return mBuildForceErrorOnNativeLibInJar; } @@ -185,6 +196,7 @@ public final class AdtPrefs extends AbstractPreferenceInitializer { store.setDefault(PREFS_HOME_PACKAGE, "android.process.acore"); //$NON-NLS-1$ store.setDefault(PREFS_MONITOR_DENSITY, 0.f); + store.setDefault(PREFS_FORMAT_XML, false); try { store.setDefault(PREFS_DEFAULT_DEBUG_KEYSTORE, diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/EditorsPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/EditorsPage.java index 472b15b..140520f 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/EditorsPage.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/EditorsPage.java @@ -19,6 +19,7 @@ package com.android.ide.eclipse.adt.internal.preferences; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.sdkuilib.internal.widgets.ResolutionChooserDialog; +import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.StringButtonFieldEditor; import org.eclipse.jface.window.Window; @@ -44,6 +45,9 @@ public class EditorsPage extends FieldEditorPreferencePage implements IWorkbench protected void createFieldEditors() { addField(new DensityFieldEditor(AdtPrefs.PREFS_MONITOR_DENSITY, "Monitor Density", getFieldEditorParent())); + addField(new BooleanFieldEditor(AdtPrefs.PREFS_FORMAT_XML, + "Automatically format the XML edited by the visual layout editor", + getFieldEditorParent())); } /** |