blob: 0fd317c1c1a957073ae05219bf13d4d1685076f8 [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.eclipse.org/org/documents/epl-v10.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ide.eclipse.adt.internal.editors.uimodel;
import com.android.SdkConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ListAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.TextAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.ui.SectionHelper;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.TableWrapData;
/**
* Represents an XML attribute which has possible built-in values, and can be modified by
* an editable Combo box.
* <p/>
* See {@link UiTextAttributeNode} for more information.
*/
public class UiListAttributeNode extends UiAbstractTextAttributeNode {
protected Combo mCombo;
public UiListAttributeNode(ListAttributeDescriptor attributeDescriptor,
UiElementNode uiParent) {
super(attributeDescriptor, uiParent);
}
/* (non-java doc)
* Creates a label widget and an associated text field.
* <p/>
* As most other parts of the android manifest editor, this assumes the
* parent uses a table layout with 2 columns.
*/
@Override
public final void createUiControl(final Composite parent, IManagedForm managedForm) {
FormToolkit toolkit = managedForm.getToolkit();
TextAttributeDescriptor desc = (TextAttributeDescriptor) getDescriptor();
Label label = toolkit.createLabel(parent, desc.getUiName());
label.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.MIDDLE));
SectionHelper.addControlTooltip(label, DescriptorsUtils.formatTooltip(desc.getTooltip()));
int style = SWT.DROP_DOWN;
mCombo = new Combo(parent, style);
TableWrapData twd = new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE);
twd.maxWidth = 100;
mCombo.setLayoutData(twd);
fillCombo();
setTextWidgetValue(getCurrentValue());
mCombo.addModifyListener(new ModifyListener() {
/**
* Sent when the text is modified, whether by the user via manual
* input or programmatic input via setText().
*/
@Override
public void modifyText(ModifyEvent e) {
onComboChange();
}
});
mCombo.addSelectionListener(new SelectionAdapter() {
/** Sent when the text is changed from a list selection. */
@Override
public void widgetSelected(SelectionEvent e) {
onComboChange();
}
});
// Remove self-reference when the widget is disposed
mCombo.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
mCombo = null;
}
});
}
protected void fillCombo() {
String[] values = getPossibleValues(null);
if (values == null) {
AdtPlugin.log(IStatus.ERROR,
"FrameworkResourceManager did not provide values yet for %1$s",
getDescriptor().getXmlLocalName());
} else {
for (String value : values) {
mCombo.add(value);
}
}
}
/**
* Get the list values, either from the initial values set in the attribute
* or by querying the framework resource parser.
*
* {@inheritDoc}
*/
@Override
public String[] getPossibleValues(String prefix) {
AttributeDescriptor descriptor = getDescriptor();
UiElementNode uiParent = getUiParent();
String attr_name = descriptor.getXmlLocalName();
String element_name = uiParent.getDescriptor().getXmlName();
// FrameworkResourceManager expects a specific prefix for the attribute.
String nsPrefix = "";
if (SdkConstants.NS_RESOURCES.equals(descriptor.getNamespaceUri())) {
nsPrefix = SdkConstants.ANDROID_NS_NAME + ':';
} else if (SdkConstants.XMLNS_URI.equals(descriptor.getNamespaceUri())) {
nsPrefix = SdkConstants.XMLNS_PREFIX;
}
attr_name = nsPrefix + attr_name;
String[] values = null;
if (descriptor instanceof ListAttributeDescriptor &&
((ListAttributeDescriptor) descriptor).getValues() != null) {
// Get enum values from the descriptor
values = ((ListAttributeDescriptor) descriptor).getValues();
}
if (values == null) {
// or from the AndroidTargetData
UiElementNode uiNode = getUiParent();
AndroidXmlEditor editor = uiNode.getEditor();
AndroidTargetData data = editor.getTargetData();
if (data != null) {
// get the great-grand-parent descriptor.
// the parent should always exist.
UiElementNode grandParentNode = uiParent.getUiParent();
String greatGrandParentNodeName = null;
if (grandParentNode != null) {
UiElementNode greatGrandParentNode = grandParentNode.getUiParent();
if (greatGrandParentNode != null) {
greatGrandParentNodeName =
greatGrandParentNode.getDescriptor().getXmlName();
}
}
values = data.getAttributeValues(element_name, attr_name, greatGrandParentNodeName);
}
}
return values;
}
@Override
public String getTextWidgetValue() {
if (mCombo != null) {
return mCombo.getText();
}
return null;
}
@Override
public final boolean isValid() {
return mCombo != null;
}
@Override
public void setTextWidgetValue(String value) {
if (mCombo != null) {
mCombo.setText(value);
}
}
/**
* Handles Combo change, either from text edit or from selection change.
* <p/>
* Simply mark the attribute as dirty if it really changed.
* The container SectionPart will collect these flag and manage them.
*/
private void onComboChange() {
if (!isInInternalTextModification() &&
!isDirty() &&
mCombo != null &&
getCurrentValue() != null &&
!mCombo.getText().equals(getCurrentValue())) {
setDirty(true);
}
}
}