• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.eclipse.org/org/documents/epl-v10.php
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.ide.eclipse.adt.internal.editors.xml;
18 
19 import com.android.ide.eclipse.adt.AdtPlugin;
20 import com.android.ide.eclipse.adt.AndroidConstants;
21 import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
22 import com.android.ide.eclipse.adt.internal.editors.FirstElementParser;
23 import com.android.ide.eclipse.adt.internal.editors.descriptors.DocumentDescriptor;
24 import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
25 import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode;
26 import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
27 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
28 import com.android.sdklib.IAndroidTarget;
29 import com.android.sdklib.SdkConstants;
30 
31 import org.eclipse.core.resources.IFile;
32 import org.eclipse.core.resources.IProject;
33 import org.eclipse.ui.IEditorInput;
34 import org.eclipse.ui.IEditorPart;
35 import org.eclipse.ui.PartInitException;
36 import org.eclipse.ui.part.FileEditorInput;
37 import org.w3c.dom.Document;
38 
39 /**
40  * Multi-page form editor for /res/xml XML files.
41  */
42 public class XmlEditor extends AndroidXmlEditor {
43 
44     public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".xml.XmlEditor"; //$NON-NLS-1$
45 
46     /** Root node of the UI element hierarchy */
47     private UiDocumentNode mUiRootNode;
48 
49     /**
50      * Creates the form editor for resources XML files.
51      */
XmlEditor()52     public XmlEditor() {
53         super();
54     }
55 
56     /**
57      * Returns the root node of the UI element hierarchy, which here
58      * is the document node.
59      */
60     @Override
getUiRootNode()61     public UiDocumentNode getUiRootNode() {
62         return mUiRootNode;
63     }
64 
65     // ---- Static ----
66 
67     /**
68      * Indicates if this is a file that this {@link XmlEditor} can handle.
69      * <p/>
70      * The {@link XmlEditor} can handle XML files that have a <searchable> or
71      * <Preferences> root XML element with the adequate xmlns:android attribute.
72      *
73      * @return True if the {@link XmlEditor} can handle that file.
74      */
canHandleFile(IFile file)75     public static boolean canHandleFile(IFile file) {
76         // we need the target of the file's project to access the descriptors.
77         IProject project = file.getProject();
78         IAndroidTarget target = Sdk.getCurrent().getTarget(project);
79         if (target != null) {
80             // Note: the target data can be null when an SDK is not finished loading yet.
81             // We can potentially arrive here when Eclipse is started with a file previously
82             // open and the resource gets refreshed -- at that point we may not have the SDK yet.
83             AndroidTargetData data = Sdk.getCurrent().getTargetData(target);
84 
85             FirstElementParser.Result result = FirstElementParser.parse(
86                     file.getLocation().toOSString(),
87                     SdkConstants.NS_RESOURCES);
88 
89             if (result != null && data != null) {
90                 String name = result.getElement();
91                 if (name != null && result.getXmlnsPrefix() != null) {
92                     DocumentDescriptor desc = data.getXmlDescriptors().getDescriptor();
93                     for (ElementDescriptor elem : desc.getChildren()) {
94                         if (elem.getXmlName().equals(name)) {
95                             // This is an element that this document can handle
96                             return true;
97                         }
98                     }
99                 }
100             }
101         }
102 
103         return false;
104     }
105 
106     // ---- Base Class Overrides ----
107 
108     /**
109      * Returns whether the "save as" operation is supported by this editor.
110      * <p/>
111      * Save-As is a valid operation for the ManifestEditor since it acts on a
112      * single source file.
113      *
114      * @see IEditorPart
115      */
116     @Override
isSaveAsAllowed()117     public boolean isSaveAsAllowed() {
118         return true;
119     }
120 
121     /**
122      * Create the various form pages.
123      */
124     @Override
createFormPages()125     protected void createFormPages() {
126         try {
127             addPage(new XmlTreePage(this));
128         } catch (PartInitException e) {
129             AdtPlugin.log(e, "Error creating nested page"); //$NON-NLS-1$
130         }
131 
132     }
133 
134     /* (non-java doc)
135      * Change the tab/title name to include the project name.
136      */
137     @Override
setInput(IEditorInput input)138     protected void setInput(IEditorInput input) {
139         super.setInput(input);
140         if (input instanceof FileEditorInput) {
141             FileEditorInput fileInput = (FileEditorInput) input;
142             IFile file = fileInput.getFile();
143             setPartName(String.format("%1$s", file.getName()));
144         }
145     }
146 
147     /**
148      * Processes the new XML Model, which XML root node is given.
149      *
150      * @param xml_doc The XML document, if available, or null if none exists.
151      */
152     @Override
xmlModelChanged(Document xml_doc)153     protected void xmlModelChanged(Document xml_doc) {
154         // init the ui root on demand
155         initUiRootNode(false /*force*/);
156 
157         mUiRootNode.loadFromXmlNode(xml_doc);
158 
159         super.xmlModelChanged(xml_doc);
160     }
161 
162     /**
163      * Creates the initial UI Root Node, including the known mandatory elements.
164      * @param force if true, a new UiRootNode is recreated even if it already exists.
165      */
166     @Override
initUiRootNode(boolean force)167     protected void initUiRootNode(boolean force) {
168         // The root UI node is always created, even if there's no corresponding XML node.
169         if (mUiRootNode == null || force) {
170             Document doc = null;
171             if (mUiRootNode != null) {
172                 doc = mUiRootNode.getXmlDocument();
173             }
174 
175             // get the target data from the opened file (and its project)
176             AndroidTargetData data = getTargetData();
177 
178             DocumentDescriptor desc;
179             if (data == null) {
180                 desc = new DocumentDescriptor("temp", null /*children*/);
181             } else {
182                 desc = data.getXmlDescriptors().getDescriptor();
183             }
184 
185             mUiRootNode = (UiDocumentNode) desc.createUiNode();
186             mUiRootNode.setEditor(this);
187 
188             onDescriptorsChanged(doc);
189         }
190     }
191 
192     // ---- Local Methods ----
193 
194     /**
195      * Reloads the UI manifest node from the XML, and calls the pages to update.
196      */
onDescriptorsChanged(Document document)197     private void onDescriptorsChanged(Document document) {
198         if (document != null) {
199             mUiRootNode.loadFromXmlNode(document);
200         } else {
201             mUiRootNode.reloadFromXmlNode(mUiRootNode.getXmlNode());
202         }
203     }
204 
205 }
206