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.animator; 18 19 import static com.android.ide.eclipse.adt.AdtConstants.EDITORS_NAMESPACE; 20 21 import com.android.annotations.NonNull; 22 import com.android.annotations.Nullable; 23 import com.android.ide.eclipse.adt.AdtUtils; 24 import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlDelegate; 25 import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor; 26 import com.android.ide.eclipse.adt.internal.editors.descriptors.DocumentDescriptor; 27 import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor; 28 import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; 29 import com.android.resources.ResourceFolderType; 30 31 import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; 32 import org.w3c.dom.Document; 33 import org.w3c.dom.Element; 34 import org.w3c.dom.Node; 35 36 /** 37 * Editor for /res/animator XML files. 38 */ 39 @SuppressWarnings("restriction") 40 public class AnimationEditorDelegate extends CommonXmlDelegate { 41 42 public static class Creator implements IDelegateCreator { 43 @Override 44 @SuppressWarnings("unchecked") 45 public AnimationEditorDelegate createForFile( 46 @NonNull CommonXmlEditor delegator, 47 @Nullable ResourceFolderType type) { 48 if (ResourceFolderType.ANIM == type || ResourceFolderType.ANIMATOR == type) { 49 return new AnimationEditorDelegate(delegator); 50 } 51 52 return null; 53 } 54 } 55 56 /** 57 * Old standalone-editor ID. 58 * Use {@link CommonXmlEditor#ID} instead. 59 */ 60 public static final String LEGACY_EDITOR_ID = 61 EDITORS_NAMESPACE + ".animator.AnimationEditor"; //$NON-NLS-1$ 62 63 /** The tag used at the root */ 64 private String mRootTag; 65 66 private AnimationEditorDelegate(CommonXmlEditor editor) { 67 super(editor, new AnimationContentAssist()); 68 editor.addDefaultTargetListener(); 69 } 70 71 @Override 72 public void delegateCreateFormPages() { 73 /* Disabled for now; doesn't work quite right 74 try { 75 addPage(new AnimatorTreePage(this)); 76 } catch (PartInitException e) { 77 AdtPlugin.log(IStatus.ERROR, "Error creating nested page"); //$NON-NLS-1$ 78 AdtPlugin.getDefault().getLog().log(e.getStatus()); 79 } 80 */ 81 } 82 83 /** 84 * Processes the new XML Model. 85 * 86 * @param xmlDoc The XML document, if available, or null if none exists. 87 */ 88 @Override 89 public void delegateXmlModelChanged(Document xmlDoc) { 90 Element rootElement = xmlDoc.getDocumentElement(); 91 if (rootElement != null) { 92 mRootTag = rootElement.getTagName(); 93 } 94 95 // create the ui root node on demand. 96 delegateInitUiRootNode(false /*force*/); 97 98 if (mRootTag != null 99 && !mRootTag.equals(getUiRootNode().getDescriptor().getXmlLocalName())) { 100 AndroidTargetData data = getEditor().getTargetData(); 101 if (data != null) { 102 ElementDescriptor descriptor; 103 if (getFolderType() == ResourceFolderType.ANIM) { 104 descriptor = data.getAnimDescriptors().getElementDescriptor(mRootTag); 105 } else { 106 descriptor = data.getAnimatorDescriptors().getElementDescriptor(mRootTag); 107 } 108 // Replace top level node now that we know the actual type 109 110 // Disconnect from old 111 getUiRootNode().setEditor(null); 112 getUiRootNode().setXmlDocument(null); 113 114 // Create new 115 setUiRootNode(descriptor.createUiNode()); 116 getUiRootNode().setXmlDocument(xmlDoc); 117 getUiRootNode().setEditor(getEditor()); 118 } 119 } 120 121 if (getUiRootNode().getDescriptor() instanceof DocumentDescriptor) { 122 getUiRootNode().loadFromXmlNode(xmlDoc); 123 } else { 124 getUiRootNode().loadFromXmlNode(rootElement); 125 } 126 } 127 128 @Override 129 public void delegateInitUiRootNode(boolean force) { 130 // The manifest UI node is always created, even if there's no corresponding XML node. 131 if (getUiRootNode() == null || force) { 132 ElementDescriptor descriptor; 133 boolean reload = false; 134 AndroidTargetData data = getEditor().getTargetData(); 135 if (data == null) { 136 descriptor = new DocumentDescriptor("temp", null /*children*/); 137 } else { 138 if (getFolderType() == ResourceFolderType.ANIM) { 139 descriptor = data.getAnimDescriptors().getElementDescriptor(mRootTag); 140 } else { 141 descriptor = data.getAnimatorDescriptors().getElementDescriptor(mRootTag); 142 } 143 reload = true; 144 } 145 setUiRootNode(descriptor.createUiNode()); 146 getUiRootNode().setEditor(getEditor()); 147 148 if (reload) { 149 onDescriptorsChanged(); 150 } 151 } 152 } 153 154 private ResourceFolderType getFolderType() { 155 String folderName = AdtUtils.getParentFolderName(getEditor().getEditorInput()); 156 if (folderName.length() > 0) { 157 return ResourceFolderType.getFolderType(folderName); 158 } 159 return ResourceFolderType.ANIMATOR; 160 } 161 162 private void onDescriptorsChanged() { 163 IStructuredModel model = getEditor().getModelForRead(); 164 if (model != null) { 165 try { 166 Node node = getEditor().getXmlDocument(model).getDocumentElement(); 167 getUiRootNode().reloadFromXmlNode(node); 168 } finally { 169 model.releaseFromRead(); 170 } 171 } 172 } 173 } 174