Home | History | Annotate | Download | only in uimodel
      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