diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java new file mode 100644 index 000000000..d9d272224 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/uimodel/UiViewElementNode.java @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2008 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.layout.uimodel; + +import static com.android.SdkConstants.ANDROID_NS_NAME; +import static com.android.SdkConstants.ANDROID_URI; +import static com.android.SdkConstants.ATTR_CLASS; +import static com.android.SdkConstants.ATTR_ORIENTATION; +import static com.android.SdkConstants.FQCN_FRAME_LAYOUT; +import static com.android.SdkConstants.LINEAR_LAYOUT; +import static com.android.SdkConstants.VALUE_VERTICAL; +import static com.android.SdkConstants.VIEW_TAG; + +import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; +import com.android.ide.eclipse.adt.internal.editors.IconFactory; +import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor; +import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor; +import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor; +import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; +import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.LayoutDescriptors; +import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor; +import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode; +import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode; +import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; +import com.android.ide.eclipse.adt.internal.sdk.Sdk; +import com.android.sdklib.IAndroidTarget; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.swt.graphics.Image; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Specialized version of {@link UiElementNode} for the {@link ViewElementDescriptor}s. + */ +public class UiViewElementNode extends UiElementNode { + + /** An AttributeDescriptor array that depends on the current UiParent. */ + private AttributeDescriptor[] mCachedAttributeDescriptors; + + public UiViewElementNode(ViewElementDescriptor elementDescriptor) { + super(elementDescriptor); + } + + /** + * Returns an AttributeDescriptor array that depends on the current UiParent. + * <p/> + * The array merges both "direct" attributes with the descriptor layout attributes. + * The array instance is cached and cleared if the UiParent is changed. + */ + @Override + public AttributeDescriptor[] getAttributeDescriptors() { + if (!getDescriptor().syncAttributes()) { + mCachedAttributeDescriptors = null; + } + if (mCachedAttributeDescriptors != null) { + return mCachedAttributeDescriptors; + } + + UiElementNode ui_parent = getUiParent(); + AttributeDescriptor[] direct_attrs = super.getAttributeDescriptors(); + mCachedAttributeDescriptors = direct_attrs; + + // Compute layout attributes: These depend on the *parent* this widget is within + AttributeDescriptor[] layout_attrs = null; + boolean need_xmlns = false; + + if (ui_parent instanceof UiDocumentNode) { + // Limitation: right now the layout behaves as if everything was + // owned by a FrameLayout. + // TODO replace by something user-configurable. + + IProject project = getEditor().getProject(); + if (project != null) { + Sdk currentSdk = Sdk.getCurrent(); + if (currentSdk != null) { + IAndroidTarget target = currentSdk.getTarget(project); + if (target != null) { + AndroidTargetData data = currentSdk.getTargetData(target); + if (data != null) { + LayoutDescriptors descriptors = data.getLayoutDescriptors(); + ViewElementDescriptor desc = + descriptors.findDescriptorByClass(FQCN_FRAME_LAYOUT); + if (desc != null) { + layout_attrs = desc.getLayoutAttributes(); + need_xmlns = true; + } + } + } + } + } + } else if (ui_parent instanceof UiViewElementNode) { + layout_attrs = + ((ViewElementDescriptor) ui_parent.getDescriptor()).getLayoutAttributes(); + } + + if (layout_attrs == null || layout_attrs.length == 0) { + return mCachedAttributeDescriptors; + } + + mCachedAttributeDescriptors = + new AttributeDescriptor[direct_attrs.length + + layout_attrs.length + + (need_xmlns ? 1 : 0)]; + System.arraycopy(direct_attrs, 0, + mCachedAttributeDescriptors, 0, + direct_attrs.length); + System.arraycopy(layout_attrs, 0, + mCachedAttributeDescriptors, direct_attrs.length, + layout_attrs.length); + if (need_xmlns) { + AttributeDescriptor desc = new XmlnsAttributeDescriptor(ANDROID_NS_NAME, ANDROID_URI); + mCachedAttributeDescriptors[direct_attrs.length + layout_attrs.length] = desc; + } + + return mCachedAttributeDescriptors; + } + + public Image getIcon() { + ElementDescriptor desc = getDescriptor(); + if (desc != null) { + Image img = null; + // Special case for the common case of vertical linear layouts: + // show vertical linear icon (the default icon shows horizontal orientation) + String uiName = desc.getUiName(); + IconFactory icons = IconFactory.getInstance(); + if (uiName.equals(LINEAR_LAYOUT)) { + Element e = (Element) getXmlNode(); + if (VALUE_VERTICAL.equals(e.getAttributeNS(ANDROID_URI, ATTR_ORIENTATION))) { + IconFactory factory = icons; + img = factory.getIcon("VerticalLinearLayout"); //$NON-NLS-1$ + } + } else if (uiName.equals(VIEW_TAG)) { + Node xmlNode = getXmlNode(); + if (xmlNode instanceof Element) { + String className = ((Element) xmlNode).getAttribute(ATTR_CLASS); + if (className != null && className.length() > 0) { + int index = className.lastIndexOf('.'); + if (index != -1) { + className = "customView"; //$NON-NLS-1$ + } + img = icons.getIcon(className); + } + } + + if (img == null) { + // Can't have both view.png and View.png; issues on case sensitive vs + // case insensitive file systems + img = icons.getIcon("View"); //$NON-NLS-1$ + } + } + if (img == null) { + img = desc.getGenericIcon(); + } + + if (img != null) { + AndroidXmlEditor editor = getEditor(); + if (editor != null) { + LayoutEditorDelegate delegate = LayoutEditorDelegate.fromEditor(editor); + if (delegate != null) { + IMarker marker = delegate.getIssueForNode(this); + if (marker != null) { + int severity = marker.getAttribute(IMarker.SEVERITY, 0); + if (severity == IMarker.SEVERITY_ERROR) { + return icons.addErrorIcon(img); + } else { + return icons.addWarningIcon(img); + } + } + } + } + + return img; + } + + return img; + } + + return AdtPlugin.getAndroidLogo(); + } + + /** + * Sets the parent of this UI node. + * <p/> + * Also removes the cached AttributeDescriptor array that depends on the current UiParent. + */ + @Override + protected void setUiParent(UiElementNode parent) { + super.setUiParent(parent); + mCachedAttributeDescriptors = null; + } +} |