diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java index 026b760cc..cab7f7306 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewInfoPart.java @@ -20,17 +20,16 @@ import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.editors.manifest.ManifestEditor; import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; import com.android.ide.eclipse.editors.ui.UiElementPart; -import com.android.ide.eclipse.editors.uimodel.UiAttributeNode; import com.android.ide.eclipse.editors.uimodel.UiElementNode; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.forms.IManagedForm; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Section; -import org.w3c.dom.Node; /** - * Generic info section part for overview page + * Generic info section part for overview page: it displays all the attributes from + * the manifest element. */ final class OverviewInfoPart extends UiElementPart { @@ -38,8 +37,8 @@ final class OverviewInfoPart extends UiElementPart { public OverviewInfoPart(Composite body, FormToolkit toolkit, ManifestEditor editor) { super(body, toolkit, editor, - null, // uiElementNode - "General Information", // section title + getManifestUiNode(editor), // uiElementNode + "Manifest General Attributes", // section title "Defines general information about the AndroidManifest.xml", // section description Section.TWISTIE | Section.EXPANDED); } @@ -64,22 +63,6 @@ final class OverviewInfoPart extends UiElementPart { return editor.getUiRootNode(); } - /** - * Retrieves the uses-sdk UI node. Since this is a mandatory node, it *always* - * exists, even if there is no matching XML node. - */ - private UiElementNode getUsesSdkUiNode(ManifestEditor editor) { - AndroidManifestDescriptors manifestDescriptors = editor.getManifestDescriptors(); - if (manifestDescriptors != null) { - ElementDescriptor desc = manifestDescriptors.getUsesSdkElement(); - return editor.getUiRootNode().findUiChildNode(desc.getXmlName()); - } - - // No manifest descriptor: we have a dummy UiRootNode, so we return that. - // The editor will be reloaded once we have the proper descriptors anyway. - return editor.getUiRootNode(); - } - /** * Overridden in order to capture the current managed form. * @@ -98,125 +81,7 @@ final class OverviewInfoPart extends UiElementPart { * SDK has changed. */ public void onSdkChanged() { + setUiElementNode(getManifestUiNode(getEditor())); createUiAttributes(mManagedForm); } - - /** - * Overridden to add the description and the ui attributes of both the - * manifest and uses-sdk UI nodes. - *

- * {@inheritDoc} - */ - @Override - protected void fillTable(Composite table, IManagedForm managedForm) { - int n = 0; - - UiElementNode uiNode = getManifestUiNode(getEditor()); - n += insertUiAttributes(uiNode, table, managedForm); - - uiNode = getUsesSdkUiNode(getEditor()); - n += insertUiAttributes(uiNode, table, managedForm); - - if (n == 0) { - createLabel(table, managedForm.getToolkit(), - "No attributes to display, waiting for SDK to finish loading...", - null /* tooltip */ ); - } - - layoutChanged(); - } - - /** - * Overridden to tests whether either the manifest or uses-sdk nodes parts are dirty. - *

- * {@inheritDoc} - * - * @return true if the part is dirty, false - * otherwise. - */ - @Override - public boolean isDirty() { - boolean dirty = super.isDirty(); - - if (!dirty) { - UiElementNode uiNode = getManifestUiNode(getEditor()); - if (uiNode != null) { - for (UiAttributeNode ui_attr : uiNode.getUiAttributes()) { - if (ui_attr.isDirty()) { - markDirty(); - dirty = true; - break; - } - } - } - } - - if (!dirty) { - UiElementNode uiNode = getUsesSdkUiNode(getEditor()); - if (uiNode != null) { - for (UiAttributeNode ui_attr : uiNode.getUiAttributes()) { - if (ui_attr.isDirty()) { - markDirty(); - dirty = true; - break; - } - } - } - } - - return dirty; - } - - /** - * Overridden to save both the manifest or uses-sdk nodes. - *

- * {@inheritDoc} - */ - @Override - public void commit(boolean onSave) { - final UiElementNode manifestUiNode = getManifestUiNode(getEditor()); - final UiElementNode usesSdkUiNode = getUsesSdkUiNode(getEditor()); - - getEditor().editXmlModel(new Runnable() { - public void run() { - if (manifestUiNode != null && manifestUiNode.isDirty()) { - for (UiAttributeNode ui_attr : manifestUiNode.getUiAttributes()) { - ui_attr.commit(); - } - } - - if (usesSdkUiNode != null && usesSdkUiNode.isDirty()) { - for (UiAttributeNode ui_attr : usesSdkUiNode.getUiAttributes()) { - ui_attr.commit(); - } - - if (!usesSdkUiNode.isDirty()) { - // Remove the XML element if it is empty. - // Rather than rely on the internal UI state, actually check that the - // XML element has no attributes and no child element so that we don't - // trash some user-generated content. - Node element = usesSdkUiNode.prepareCommit(); - if (element != null && - !element.hasAttributes() && - !element.hasChildNodes()) { - // Important note: we MUST NOT use usesSdkUiNode.deleteXmlNode() - // here, as it would clear the UiAttribute list and thus break the - // link between the controls and the ui attribute field. - // Instead what we want is simply to remove the XML node and let the - // UiElementNode node know. - Node parent = element.getParentNode(); - if (parent != null) { - parent.removeChild(element); - usesSdkUiNode.loadFromXmlNode(null /*xml_node*/); - } - } - } - } - } - }); - - // We need to call super's commit after we synchronized the nodes to make sure we - // reset the dirty flag after all the side effects from committing have occurred. - super.commit(onSave); - } } diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java index 62954bdb8..a06cc7455 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/manifest/pages/OverviewPage.java @@ -17,15 +17,23 @@ package com.android.ide.eclipse.editors.manifest.pages; import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.ide.eclipse.editors.descriptors.ElementDescriptor; import com.android.ide.eclipse.editors.manifest.ManifestEditor; +import com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptors; +import com.android.ide.eclipse.editors.ui.tree.UiTreeBlock; +import com.android.ide.eclipse.editors.uimodel.UiElementNode; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.forms.IManagedForm; import org.eclipse.ui.forms.editor.FormPage; -import org.eclipse.ui.forms.widgets.ColumnLayout; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; +import java.util.ArrayList; +import java.util.HashSet; + /** * Page for overview settings, part of the AndroidManifest form editor. @@ -45,9 +53,11 @@ public final class OverviewPage extends FormPage { private OverviewInfoPart mOverviewPart; /** Overview link part */ private OverviewLinksPart mOverviewLinkPart; + + private UiTreeBlock mTreeBlock; public OverviewPage(ManifestEditor editor) { - super(editor, PAGE_ID, "Overview"); // tab's label, user visible, keep it short + super(editor, PAGE_ID, "Manifest"); // tab's label, user visible, keep it short mEditor = editor; } @@ -60,21 +70,40 @@ public final class OverviewPage extends FormPage { protected void createFormContent(IManagedForm managedForm) { super.createFormContent(managedForm); ScrolledForm form = managedForm.getForm(); - form.setText("Android Manifest Overview"); + form.setText("Android Manifest"); form.setImage(AdtPlugin.getAndroidLogo()); Composite body = form.getBody(); FormToolkit toolkit = managedForm.getToolkit(); - ColumnLayout cl = new ColumnLayout(); - cl.minNumColumns = cl.maxNumColumns = 1; - body.setLayout(cl); + + // Usually we would set a ColumnLayout on body here. However the presence of the + // UiTreeBlock forces a GridLayout with one column so we comply with it. + mOverviewPart = new OverviewInfoPart(body, toolkit, mEditor); + mOverviewPart.getSection().setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); managedForm.addPart(mOverviewPart); - managedForm.addPart(new OverviewExportPart(this, body, toolkit, mEditor)); + + newManifestExtrasPart(managedForm); + + OverviewExportPart exportPart = new OverviewExportPart(this, body, toolkit, mEditor); + exportPart.getSection().setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); + managedForm.addPart(exportPart); + mOverviewLinkPart = new OverviewLinksPart(body, toolkit, mEditor); + mOverviewLinkPart.getSection().setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); managedForm.addPart(mOverviewLinkPart); } + private void newManifestExtrasPart(IManagedForm managedForm) { + UiElementNode manifest = mEditor.getUiRootNode(); + mTreeBlock = new UiTreeBlock(mEditor, manifest, + true /* autoCreateRoot */, + computeManifestExtraFilters(), + "Manifest Extras", + "Extra manifest elements"); + mTreeBlock.createContent(managedForm); + } + /** * Changes and refreshes the Application UI node handle by the sub parts. */ @@ -86,5 +115,43 @@ public final class OverviewPage extends FormPage { if (mOverviewLinkPart != null) { mOverviewLinkPart.onSdkChanged(); } + + if (mTreeBlock != null) { + UiElementNode manifest = mEditor.getUiRootNode(); + mTreeBlock.changeRootAndDescriptors(manifest, + computeManifestExtraFilters(), + true /* refresh */); + } + } + + private ElementDescriptor[] computeManifestExtraFilters() { + UiElementNode manifest = mEditor.getUiRootNode(); + AndroidManifestDescriptors manifestDescriptor = mEditor.getManifestDescriptors(); + + if (manifestDescriptor == null) { + return null; + } + + // get the elements we want to exclude + HashSet excludes = new HashSet(); + excludes.add(manifestDescriptor.getApplicationElement()); + excludes.add(manifestDescriptor.getInstrumentationElement()); + excludes.add(manifestDescriptor.getPermissionElement()); + excludes.add(manifestDescriptor.getPermissionGroupElement()); + excludes.add(manifestDescriptor.getPermissionTreeElement()); + excludes.add(manifestDescriptor.getUsesPermissionElement()); + + // walk through the known children of the manifest descriptor and keep what's not excluded + ArrayList descriptorFilters = new ArrayList(); + for (ElementDescriptor child : manifest.getDescriptor().getChildren()) { + if (!excludes.contains(child)) { + descriptorFilters.add(child); + } + } + + if (descriptorFilters.size() == 0) { + return null; + } + return descriptorFilters.toArray(new ElementDescriptor[descriptorFilters.size()]); } }