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.uimodel; 18 19 import com.android.ide.common.xml.XmlAttributeSortOrder; 20 import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; 21 import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor; 22 23 import org.eclipse.swt.widgets.Composite; 24 import org.eclipse.ui.forms.IManagedForm; 25 import org.w3c.dom.Node; 26 27 /** 28 * Represents an XML attribute that can be modified by the XML editor's user interface. 29 * <p/> 30 * The characteristics of an {@link UiAttributeNode} are declared by a 31 * corresponding {@link AttributeDescriptor}. 32 * <p/> 33 * This is an abstract class. Derived classes must implement the creation of the UI 34 * and manage its synchronization with the XML. 35 */ 36 public abstract class UiAttributeNode implements Comparable<UiAttributeNode> { 37 38 private AttributeDescriptor mDescriptor; 39 private UiElementNode mUiParent; 40 private boolean mIsDirty; 41 private boolean mHasError; 42 43 /** Creates a new {@link UiAttributeNode} linked to a specific {@link AttributeDescriptor} 44 * and the corresponding runtime {@link UiElementNode} parent. */ 45 public UiAttributeNode(AttributeDescriptor attributeDescriptor, UiElementNode uiParent) { 46 mDescriptor = attributeDescriptor; 47 mUiParent = uiParent; 48 } 49 50 /** Returns the {@link AttributeDescriptor} specific to this UI attribute node */ 51 public final AttributeDescriptor getDescriptor() { 52 return mDescriptor; 53 } 54 55 /** Returns the {@link UiElementNode} that owns this {@link UiAttributeNode} */ 56 public final UiElementNode getUiParent() { 57 return mUiParent; 58 } 59 60 /** Returns the current value of the node. */ 61 public abstract String getCurrentValue(); 62 63 /** 64 * @return True if the attribute has been changed since it was last loaded 65 * from the XML model. 66 */ 67 public final boolean isDirty() { 68 return mIsDirty; 69 } 70 71 /** 72 * Sets whether the attribute is dirty and also notifies the editor some part's dirty 73 * flag as changed. 74 * <p/> 75 * Subclasses should set the to true as a result of user interaction with the widgets in 76 * the section and then should set to false when the commit() method completed. 77 * 78 * @param isDirty the new value to set the dirty-flag to 79 */ 80 public void setDirty(boolean isDirty) { 81 boolean wasDirty = mIsDirty; 82 mIsDirty = isDirty; 83 // TODO: for unknown attributes, getParent() != null && getParent().getEditor() != null 84 if (wasDirty != isDirty) { 85 AndroidXmlEditor editor = getUiParent().getEditor(); 86 if (editor != null) { 87 editor.editorDirtyStateChanged(); 88 } 89 } 90 } 91 92 /** 93 * Sets the error flag value. 94 * @param errorFlag the error flag 95 */ 96 public final void setHasError(boolean errorFlag) { 97 mHasError = errorFlag; 98 } 99 100 /** 101 * Returns whether this node has errors. 102 */ 103 public final boolean hasError() { 104 return mHasError; 105 } 106 107 /** 108 * Called once by the parent user interface to creates the necessary 109 * user interface to edit this attribute. 110 * <p/> 111 * This method can be called more than once in the life cycle of an UI node, 112 * typically when the UI is part of a master-detail tree, as pages are swapped. 113 * 114 * @param parent The composite where to create the user interface. 115 * @param managedForm The managed form owning this part. 116 */ 117 public abstract void createUiControl(Composite parent, IManagedForm managedForm); 118 119 /** 120 * Used to get a list of all possible values for this UI attribute. 121 * <p/> 122 * This is used, among other things, by the XML Content Assists to complete values 123 * for an attribute. 124 * <p/> 125 * Implementations that do not have any known values should return null. 126 * 127 * @param prefix An optional prefix string, which is whatever the user has already started 128 * typing. Can be null or an empty string. The implementation can use this to filter choices 129 * and only return strings that match this prefix. A lazy or default implementation can 130 * simply ignore this and return everything. 131 * @return A list of possible completion values, and empty array or null. 132 */ 133 public abstract String[] getPossibleValues(String prefix); 134 135 /** 136 * Called when the XML is being loaded or has changed to 137 * update the value held by this user interface attribute node. 138 * <p/> 139 * The XML Node <em>may</em> be null, which denotes that the attribute is not 140 * specified in the XML model. In general, this means the "default" value of the 141 * attribute should be used. 142 * <p/> 143 * The caller doesn't really know if attributes have changed, 144 * so it will call this to refresh the attribute anyway. It's up to the 145 * UI implementation to minimize refreshes. 146 * 147 * @param node the node to read the value from 148 */ 149 public abstract void updateValue(Node node); 150 151 /** 152 * Called by the user interface when the editor is saved or its state changed 153 * and the modified attributes must be committed (i.e. written) to the XML model. 154 * <p/> 155 * Important behaviors: 156 * <ul> 157 * <li>The caller *must* have called IStructuredModel.aboutToChangeModel before. 158 * The implemented methods must assume it is safe to modify the XML model. 159 * <li>On success, the implementation *must* call setDirty(false). 160 * <li>On failure, the implementation can fail with an exception, which 161 * is trapped and logged by the caller, or do nothing, whichever is more 162 * appropriate. 163 * </ul> 164 */ 165 public abstract void commit(); 166 167 // ---- Implements Comparable ---- 168 169 @Override 170 public int compareTo(UiAttributeNode o) { 171 return XmlAttributeSortOrder.compareAttributes(mDescriptor.getXmlLocalName(), 172 o.mDescriptor.getXmlLocalName()); 173 } 174 } 175