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.manifest.pages;
18 
19 import com.android.ide.eclipse.adt.AdtPlugin;
20 import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
21 import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
22 import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestEditor;
23 import com.android.ide.eclipse.adt.internal.editors.ui.UiElementPart;
24 import com.android.ide.eclipse.adt.internal.editors.uimodel.IUiUpdateListener;
25 import com.android.ide.eclipse.adt.internal.editors.uimodel.UiAttributeNode;
26 import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
27 
28 import org.eclipse.core.runtime.IStatus;
29 import org.eclipse.swt.widgets.Composite;
30 import org.eclipse.swt.widgets.Control;
31 import org.eclipse.ui.forms.IManagedForm;
32 import org.eclipse.ui.forms.widgets.FormToolkit;
33 import org.eclipse.ui.forms.widgets.Section;
34 
35 /**
36  * Application's attributes section part for Application page.
37  * <p/>
38  * This part is displayed at the top of the application page and displays all the possible
39  * attributes of an application node in the AndroidManifest (icon, class name, label, etc.)
40  */
41 final class ApplicationAttributesPart extends UiElementPart {
42 
43     /** Listen to changes to the UI node for <application> and updates the UI */
44     private AppNodeUpdateListener mAppNodeUpdateListener;
45     /** ManagedForm needed to create the UI controls */
46     private IManagedForm mManagedForm;
47 
ApplicationAttributesPart(Composite body, FormToolkit toolkit, ManifestEditor editor, UiElementNode applicationUiNode)48     public ApplicationAttributesPart(Composite body, FormToolkit toolkit, ManifestEditor editor,
49             UiElementNode applicationUiNode) {
50         super(body, toolkit, editor, applicationUiNode,
51                 "Application Attributes", // section title
52                 "Defines the attributes specific to the application.", // section description
53                 Section.TWISTIE | Section.EXPANDED);
54     }
55 
56     /**
57      * Changes and refreshes the Application UI node handle by the this part.
58      */
59     @Override
setUiElementNode(UiElementNode uiElementNode)60     public void setUiElementNode(UiElementNode uiElementNode) {
61         super.setUiElementNode(uiElementNode);
62 
63         createUiAttributes(mManagedForm);
64     }
65 
66     /* (non-java doc)
67      * Create the controls to edit the attributes for the given ElementDescriptor.
68      * <p/>
69      * This MUST not be called by the constructor. Instead it must be called from
70      * <code>initialize</code> (i.e. right after the form part is added to the managed form.)
71      * <p/>
72      * Derived classes can override this if necessary.
73      *
74      * @param managedForm The owner managed form
75      */
76     @Override
createFormControls(final IManagedForm managedForm)77     protected void createFormControls(final IManagedForm managedForm) {
78         mManagedForm = managedForm;
79         setTable(createTableLayout(managedForm.getToolkit(), 4 /* numColumns */));
80 
81         mAppNodeUpdateListener = new AppNodeUpdateListener();
82         getUiElementNode().addUpdateListener(mAppNodeUpdateListener);
83 
84         createUiAttributes(mManagedForm);
85     }
86 
87     @Override
dispose()88     public void dispose() {
89         super.dispose();
90         if (getUiElementNode() != null && mAppNodeUpdateListener != null) {
91             getUiElementNode().removeUpdateListener(mAppNodeUpdateListener);
92             mAppNodeUpdateListener = null;
93         }
94     }
95 
96     @Override
createUiAttributes(IManagedForm managedForm)97     protected void createUiAttributes(IManagedForm managedForm) {
98         Composite table = getTable();
99         if (table == null || managedForm == null) {
100             return;
101         }
102 
103         // Remove any old UI controls
104         for (Control c : table.getChildren()) {
105             c.dispose();
106         }
107 
108         UiElementNode uiElementNode = getUiElementNode();
109         AttributeDescriptor[] attr_desc_list = uiElementNode.getAttributeDescriptors();
110 
111         // Display the attributes in 2 columns:
112         // attr 0 | attr 4
113         // attr 1 | attr 5
114         // attr 2 | attr 6
115         // attr 3 | attr 7
116         // that is we have to fill the grid in order 0, 4, 1, 5, 2, 6, 3, 7
117         // thus index = i/2 + (i is odd * n/2)
118         int n = attr_desc_list.length;
119         int n2 = (int) Math.ceil(n / 2.0);
120         for (int i = 0; i < n; i++) {
121             AttributeDescriptor attr_desc = attr_desc_list[i / 2 + (i & 1) * n2];
122             if (attr_desc instanceof XmlnsAttributeDescriptor) {
123                 // Do not show hidden attributes
124                 continue;
125             }
126 
127             UiAttributeNode ui_attr = uiElementNode.findUiAttribute(attr_desc);
128             if (ui_attr != null) {
129                 ui_attr.createUiControl(table, managedForm);
130             } else {
131                 // The XML has an extra attribute which wasn't declared in
132                 // AndroidManifestDescriptors. This is not a problem, we just ignore it.
133                 AdtPlugin.log(IStatus.WARNING,
134                         "Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$
135                         attr_desc.getXmlLocalName(),
136                         uiElementNode.getDescriptor().getXmlName());
137             }
138         }
139 
140         if (n == 0) {
141             createLabel(table, managedForm.getToolkit(),
142                     "No attributes to display, waiting for SDK to finish loading...",
143                     null /* tooltip */ );
144         }
145 
146         // Initialize the enabled/disabled state
147         if (mAppNodeUpdateListener != null) {
148             mAppNodeUpdateListener.uiElementNodeUpdated(uiElementNode, null /* state, not used */);
149         }
150 
151         // Tell the section that the layout has changed.
152         layoutChanged();
153     }
154 
155     /**
156      * This listener synchronizes the UI with the actual presence of the application XML node.
157      */
158     private class AppNodeUpdateListener implements IUiUpdateListener {
159         @Override
uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state)160         public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) {
161             // The UiElementNode for the application XML node always exists, even
162             // if there is no corresponding XML node in the XML file.
163             //
164             // We enable the UI here if the XML node is not null.
165             Composite table = getTable();
166             boolean exists = (ui_node.getXmlNode() != null);
167             if (table != null && table.getEnabled() != exists) {
168                 table.setEnabled(exists);
169                 for (Control c : table.getChildren()) {
170                     c.setEnabled(exists);
171                 }
172             }
173         }
174     }
175 }
176