FileDocCategorySizeDatePackage
ManifestEditor.javaAPI DocAndroid 1.5 API14224Wed May 06 22:41:10 BST 2009com.android.ide.eclipse.editors.manifest

ManifestEditor

public final class ManifestEditor extends com.android.ide.eclipse.editors.AndroidEditor
Multi-page form editor for AndroidManifest.xml.

Fields Summary
private static final String
EMPTY
private com.android.ide.eclipse.editors.uimodel.UiElementNode
mUiManifestNode
Root node of the UI element hierarchy
private com.android.ide.eclipse.editors.manifest.pages.ApplicationPage
mAppPage
The Application Page tab
private com.android.ide.eclipse.editors.manifest.pages.OverviewPage
mOverviewPage
The Overview Manifest Page tab
private com.android.ide.eclipse.editors.manifest.pages.PermissionPage
mPermissionPage
The Permission Page tab
private com.android.ide.eclipse.editors.manifest.pages.InstrumentationPage
mInstrumentationPage
The Instrumentation Page tab
private com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IFileListener
mMarkerMonitor
Constructors Summary
public ManifestEditor()
Creates the form editor for AndroidManifest.xml.

    

               
      
        super();
    
Methods Summary
protected voidcreateFormPages()
Creates the various form pages.

        try {
            addPage(mOverviewPage = new OverviewPage(this));
            addPage(mAppPage = new ApplicationPage(this));
            addPage(mPermissionPage = new PermissionPage(this));
            addPage(mInstrumentationPage = new InstrumentationPage(this));
        } catch (PartInitException e) {
            AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
        }
    
public voiddispose()

        super.dispose();

        ResourceMonitor.getMonitor().removeFileListener(mMarkerMonitor);
    
private org.eclipse.core.resources.IFilegetInputFile()
Returns the {@link IFile} being edited, or null if it couldn't be computed.

        IEditorInput input = getEditorInput();
        if (input instanceof FileEditorInput) {
            FileEditorInput fileInput = (FileEditorInput) input;
            return fileInput.getFile();
        }
        
        return null;
    
public com.android.ide.eclipse.editors.manifest.descriptors.AndroidManifestDescriptorsgetManifestDescriptors()
Returns the Manifest descriptors for the file being edited.

        AndroidTargetData data = getTargetData();
        if (data != null) {
            return data.getManifestDescriptors();
        }
        
        return null;
    
public com.android.ide.eclipse.editors.uimodel.UiElementNodegetUiRootNode()
Return the root node of the UI element hierarchy, which here is the "manifest" node.

        return mUiManifestNode;
    
protected voidinitUiRootNode(boolean force)
Creates the initial UI Root Node, including the known mandatory elements.

param
force if true, a new UiManifestNode is recreated even if it already exists.

        // The manifest UI node is always created, even if there's no corresponding XML node.
        if (mUiManifestNode != null && force == false) {
            return;
        }
        
        AndroidManifestDescriptors manifestDescriptor = getManifestDescriptors();
        
        if (manifestDescriptor != null) {
            // save the old manifest node if it exists
            UiElementNode oldManifestNode = mUiManifestNode;

            ElementDescriptor manifestElement = manifestDescriptor.getManifestElement();   
            mUiManifestNode = manifestElement.createUiNode();
            mUiManifestNode.setEditor(this);
    
            // Similarly, always create the /manifest/application and /manifest/uses-sdk nodes
            ElementDescriptor appElement = manifestDescriptor.getApplicationElement();
            boolean present = false;
            for (UiElementNode ui_node : mUiManifestNode.getUiChildren()) {
                if (ui_node.getDescriptor() == appElement) {
                    present = true;
                    break;
                }
            }
            if (!present) {
                mUiManifestNode.appendNewUiChild(appElement);
            }

            appElement = manifestDescriptor.getUsesSdkElement();
            present = false;
            for (UiElementNode ui_node : mUiManifestNode.getUiChildren()) {
                if (ui_node.getDescriptor() == appElement) {
                    present = true;
                    break;
                }
            }
            if (!present) {
                mUiManifestNode.appendNewUiChild(appElement);
            }

            if (oldManifestNode != null) {
                onDescriptorsChanged(oldManifestNode);
            }
        } else {
            // create a dummy descriptor/uinode until we have real descriptors
            ElementDescriptor desc = new ElementDescriptor("manifest", //$NON-NLS-1$
                    "temporary descriptors due to missing decriptors", //$NON-NLS-1$
                    null /*tooltip*/, null /*sdk_url*/, null /*attributes*/,
                    null /*children*/, false /*mandatory*/);
            mUiManifestNode = desc.createUiNode();
            mUiManifestNode.setEditor(this);
        }
    
public booleanisSaveAsAllowed()
Returns whether the "save as" operation is supported by this editor.

Save-As is a valid operation for the ManifestEditor since it acts on a single source file.

see
IEditorPart

        return true;
    
private voidloadFromXml(org.w3c.dom.Document xmlDoc)

        mUiManifestNode.setXmlDocument(xmlDoc);
        if (xmlDoc != null) {
            ElementDescriptor manifest_desc = mUiManifestNode.getDescriptor();
            try {
                XPath xpath = AndroidXPathFactory.newXPath();
                Node node = (Node) xpath.evaluate("/" + manifest_desc.getXmlName(),  //$NON-NLS-1$
                        xmlDoc,
                        XPathConstants.NODE);
                assert node != null && node.getNodeName().equals(manifest_desc.getXmlName());

                // Refresh the manifest UI node and all its descendants 
                mUiManifestNode.loadFromXmlNode(node);
            } catch (XPathExpressionException e) {
                AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$
                        manifest_desc.getXmlName());
            }
        }
    
private voidonDescriptorsChanged(com.android.ide.eclipse.editors.uimodel.UiElementNode oldManifestNode)

        mUiManifestNode.reloadFromXmlNode(oldManifestNode.getXmlNode());

        if (mOverviewPage != null) {
            mOverviewPage.refreshUiApplicationNode();
        }

        if (mAppPage != null) {
            mAppPage.refreshUiApplicationNode();
        }
        
        if (mPermissionPage != null) {
            mPermissionPage.refreshUiNode();
        }
        
        if (mInstrumentationPage != null) {
            mInstrumentationPage.refreshUiNode();
        }
    
private voidprocessMarker(org.eclipse.core.resources.IMarker marker, java.util.List nodeList, int kind)
Processes a new/old/updated marker.

param
marker The marker being added/removed/changed
param
nodeList the list of activity/service/provider/receiver nodes.
param
kind the change kind. Can be {@link IResourceDelta#ADDED}, {@link IResourceDelta#REMOVED}, or {@link IResourceDelta#CHANGED}

        // get the data from the marker
        String nodeType = marker.getAttribute(AndroidConstants.MARKER_ATTR_TYPE, EMPTY);
        if (nodeType == EMPTY) {
            return;
        }
        
        String className = marker.getAttribute(AndroidConstants.MARKER_ATTR_CLASS, EMPTY);
        if (className == EMPTY) {
            return;
        }

        for (UiElementNode ui_node : nodeList) {
            if (ui_node.getDescriptor().getXmlName().equals(nodeType)) {
                for (UiAttributeNode attr : ui_node.getUiAttributes()) {
                    if (attr.getDescriptor().getXmlLocalName().equals(
                            AndroidManifestDescriptors.ANDROID_NAME_ATTR)) {
                        if (attr.getCurrentValue().equals(className)) {
                            if (kind == IResourceDelta.REMOVED) {
                                attr.setHasError(false);
                            } else {
                                attr.setHasError(true);
                            }
                            return;
                        }
                    }
                }
            }
        }
    
private voidprocessMarkerChanges(org.eclipse.core.resources.IMarkerDelta[] markerDeltas)
Processes a {@link IMarker} change.

param
markerDeltas the list of {@link IMarkerDelta}

        AndroidManifestDescriptors descriptors = getManifestDescriptors();
        if (descriptors != null && descriptors.getApplicationElement() != null) {
            UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
                    descriptors.getApplicationElement().getXmlName());
            List<UiElementNode> children = app_ui_node.getUiChildren();
    
            for (IMarkerDelta markerDelta : markerDeltas) {
                processMarker(markerDelta.getMarker(), children, markerDelta.getKind());
            }
        }
    
protected voidsetInput(org.eclipse.ui.IEditorInput input)

        super.setInput(input);
        IFile inputFile = getInputFile();
        if (inputFile != null) {
            startMonitoringMarkers();
            setPartName(String.format("%1$s Manifest", inputFile.getProject().getName()));
        }
    
private voidstartMonitoringMarkers()
Reads and processes the current markers and adds a listener for marker changes.

        final IFile inputFile = getInputFile();
        if (inputFile != null) {
            updateFromExistingMarkers(inputFile);
            
            mMarkerMonitor = new IFileListener() {
                public void fileChanged(IFile file, IMarkerDelta[] markerDeltas, int kind) {
                    if (file.equals(inputFile)) {
                        processMarkerChanges(markerDeltas);
                    }
                }
            };
            
            ResourceMonitor.getMonitor().addFileListener(mMarkerMonitor, IResourceDelta.CHANGED);
        }
    
private voidupdateFromExistingMarkers(org.eclipse.core.resources.IFile inputFile)
Processes the markers of the specified {@link IFile} and updates the error status of {@link UiElementNode}s and {@link UiAttributeNode}s.

param
inputFile the file being edited.

        try {
            // get the markers for the file
            IMarker[] markers = inputFile.findMarkers(AndroidConstants.MARKER_ANDROID, true,
                    IResource.DEPTH_ZERO);
            
            AndroidManifestDescriptors desc = getManifestDescriptors();
            if (desc != null) {
                ElementDescriptor appElement = desc.getApplicationElement();
                
                if (appElement != null) {
                    UiElementNode app_ui_node = mUiManifestNode.findUiChildNode(
                            appElement.getXmlName());
                    List<UiElementNode> children = app_ui_node.getUiChildren();

                    for (IMarker marker : markers) {
                        processMarker(marker, children, IResourceDelta.ADDED);
                    }
                }
            }
            
        } catch (CoreException e) {
            // findMarkers can throw an exception, in which case, we'll do nothing.
        }
    
protected voidxmlModelChanged(org.w3c.dom.Document xml_doc)
Processes the new XML Model, which XML root node is given.

param
xml_doc The XML document, if available, or null if none exists.

        // create the ui root node on demand.
        initUiRootNode(false /*force*/);

        loadFromXml(xml_doc);

        super.xmlModelChanged(xml_doc);