1 /* 2 * Copyright (C) 2007 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.values; 18 19 import com.android.annotations.NonNull; 20 import com.android.annotations.Nullable; 21 import com.android.ide.eclipse.adt.AdtConstants; 22 import com.android.ide.eclipse.adt.AdtPlugin; 23 import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlDelegate; 24 import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor; 25 import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor; 26 import com.android.ide.eclipse.adt.internal.editors.values.descriptors.ValuesDescriptors; 27 import com.android.resources.ResourceFolderType; 28 import com.android.xml.AndroidXPathFactory; 29 30 import org.eclipse.core.runtime.IStatus; 31 import org.eclipse.ui.PartInitException; 32 import org.w3c.dom.Document; 33 import org.w3c.dom.Node; 34 35 import javax.xml.xpath.XPath; 36 import javax.xml.xpath.XPathConstants; 37 import javax.xml.xpath.XPathExpressionException; 38 39 /** 40 * Multi-page form editor for /res/values XML files. 41 */ 42 public class ValuesEditorDelegate extends CommonXmlDelegate { 43 44 public static class Creator implements IDelegateCreator { 45 @Override 46 @SuppressWarnings("unchecked") 47 public ValuesEditorDelegate createForFile( 48 @NonNull CommonXmlEditor delegator, 49 @Nullable ResourceFolderType type) { 50 if (ResourceFolderType.VALUES == type) { 51 return new ValuesEditorDelegate(delegator); 52 } 53 54 return null; 55 } 56 } 57 58 /** 59 * Old standalone-editor ID. 60 * Use {@link CommonXmlEditor#ID} instead. 61 */ 62 public static final String LEGACY_EDITOR_ID = 63 AdtConstants.EDITORS_NAMESPACE + ".resources.ResourcesEditor"; //$NON-NLS-1$ 64 65 66 /** 67 * Creates the form editor for resources XML files. 68 */ 69 private ValuesEditorDelegate(CommonXmlEditor editor) { 70 super(editor, new ValuesContentAssist()); 71 editor.addDefaultTargetListener(); 72 } 73 74 // ---- Base Class Overrides ---- 75 76 /** 77 * Create the various form pages. 78 */ 79 @Override 80 public void delegateCreateFormPages() { 81 try { 82 getEditor().addPage(new ValuesTreePage(getEditor())); 83 } catch (PartInitException e) { 84 AdtPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$ 85 AdtPlugin.getDefault().getLog().log(e.getStatus()); 86 } 87 } 88 89 /** 90 * Processes the new XML Model, which XML root node is given. 91 * 92 * @param xml_doc The XML document, if available, or null if none exists. 93 */ 94 @Override 95 public void delegateXmlModelChanged(Document xml_doc) { 96 // init the ui root on demand 97 delegateInitUiRootNode(false /*force*/); 98 99 getUiRootNode().setXmlDocument(xml_doc); 100 if (xml_doc != null) { 101 ElementDescriptor resources_desc = 102 ValuesDescriptors.getInstance().getElementDescriptor(); 103 try { 104 XPath xpath = AndroidXPathFactory.newXPath(); 105 Node node = (Node) xpath.evaluate("/" + resources_desc.getXmlName(), //$NON-NLS-1$ 106 xml_doc, 107 XPathConstants.NODE); 108 // Node can be null _or_ it must be the element we searched for. 109 assert node == null || node.getNodeName().equals(resources_desc.getXmlName()); 110 111 // Refresh the manifest UI node and all its descendants 112 getUiRootNode().loadFromXmlNode(node); 113 } catch (XPathExpressionException e) { 114 AdtPlugin.log(e, "XPath error when trying to find '%s' element in XML.", //$NON-NLS-1$ 115 resources_desc.getXmlName()); 116 } 117 } 118 } 119 120 /** 121 * Creates the initial UI Root Node, including the known mandatory elements. 122 * @param force if true, a new UiRootNode is recreated even if it already exists. 123 */ 124 @Override 125 public void delegateInitUiRootNode(boolean force) { 126 // The manifest UI node is always created, even if there's no corresponding XML node. 127 if (getUiRootNode() == null || force) { 128 ElementDescriptor resources_desc = 129 ValuesDescriptors.getInstance().getElementDescriptor(); 130 setUiRootNode(resources_desc.createUiNode()); 131 getUiRootNode().setEditor(getEditor()); 132 133 onDescriptorsChanged(); 134 } 135 } 136 137 // ---- Local methods ---- 138 139 private void onDescriptorsChanged() { 140 // nothing to be done, as the descriptor are static for now. 141 // FIXME Update when the descriptors are not static 142 } 143 } 144 145