| /* |
| * Copyright (C) 2012 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.properties; |
| |
| import static com.android.SdkConstants.ATTR_LAYOUT_MARGIN; |
| import static com.android.SdkConstants.ATTR_LAYOUT_RESOURCE_PREFIX; |
| |
| import com.android.annotations.NonNull; |
| import com.android.annotations.Nullable; |
| import com.android.ide.common.api.IAttributeInfo; |
| import com.android.ide.eclipse.adt.AdtPlugin; |
| import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor; |
| 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.layout.gle2.GraphicalEditorPart; |
| import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ViewHierarchy; |
| import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode; |
| |
| import org.eclipse.jface.fieldassist.IContentProposal; |
| import org.eclipse.jface.fieldassist.IContentProposalProvider; |
| import org.eclipse.jface.viewers.ILabelProvider; |
| import org.eclipse.jface.viewers.LabelProvider; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.ui.views.properties.IPropertyDescriptor; |
| import org.eclipse.wb.internal.core.model.property.Property; |
| import org.eclipse.wb.internal.core.model.property.editor.PropertyEditor; |
| import org.eclipse.wb.internal.core.model.property.table.PropertyTooltipProvider; |
| import org.eclipse.wb.internal.core.model.property.table.PropertyTooltipTextProvider; |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.Element; |
| |
| import java.util.Map; |
| |
| /** |
| * An Android XML property |
| */ |
| class XmlProperty extends Property { |
| private PropertyFactory mFactory; |
| final AttributeDescriptor mDescriptor; |
| private UiViewElementNode mNode; |
| private Property mParent; |
| |
| XmlProperty( |
| @NonNull PropertyEditor editor, |
| @NonNull PropertyFactory factory, |
| @NonNull UiViewElementNode node, |
| @NonNull AttributeDescriptor descriptor) { |
| super(editor); |
| mFactory = factory; |
| mNode = node; |
| mDescriptor = descriptor; |
| } |
| |
| @NonNull |
| public PropertyFactory getFactory() { |
| return mFactory; |
| } |
| |
| @NonNull |
| public UiViewElementNode getNode() { |
| return mNode; |
| } |
| |
| @NonNull |
| public AttributeDescriptor getDescriptor() { |
| return mDescriptor; |
| } |
| |
| @Override |
| @NonNull |
| public String getName() { |
| return mDescriptor.getXmlLocalName(); |
| } |
| |
| @Override |
| @NonNull |
| public String getTitle() { |
| String name = mDescriptor.getXmlLocalName(); |
| int nameLength = name.length(); |
| |
| if (name.startsWith(ATTR_LAYOUT_RESOURCE_PREFIX)) { |
| if (name.startsWith(ATTR_LAYOUT_MARGIN) |
| && nameLength > ATTR_LAYOUT_MARGIN.length()) { |
| name = name.substring(ATTR_LAYOUT_MARGIN.length()); |
| } else { |
| name = name.substring(ATTR_LAYOUT_RESOURCE_PREFIX.length()); |
| } |
| } |
| |
| // Capitalize |
| name = DescriptorsUtils.capitalize(name); |
| |
| // If we're nested within a complex property, say "Line Spacing", don't |
| // include "Line Spacing " as a prefix for each property here |
| if (mParent != null) { |
| String parentTitle = mParent.getTitle(); |
| if (name.startsWith(parentTitle)) { |
| int parentTitleLength = parentTitle.length(); |
| if (parentTitleLength < nameLength) { |
| if (nameLength > parentTitleLength && |
| Character.isWhitespace(name.charAt(parentTitleLength))) { |
| parentTitleLength++; |
| } |
| name = name.substring(parentTitleLength); |
| } |
| } |
| } |
| |
| return name; |
| } |
| |
| @Override |
| public <T> T getAdapter(Class<T> adapter) { |
| // tooltip |
| if (adapter == PropertyTooltipProvider.class) { |
| return adapter.cast(new PropertyTooltipTextProvider() { |
| @Override |
| protected String getText(Property p) throws Exception { |
| if (mDescriptor instanceof IPropertyDescriptor) { |
| IPropertyDescriptor d = (IPropertyDescriptor) mDescriptor; |
| return d.getDescription(); |
| } |
| |
| return null; |
| } |
| }); |
| } else if (adapter == IContentProposalProvider.class) { |
| IAttributeInfo info = mDescriptor.getAttributeInfo(); |
| if (info != null) { |
| return adapter.cast(new PropertyValueCompleter(this)); |
| } |
| // Fallback: complete values on resource values |
| return adapter.cast(new ResourceValueCompleter(this)); |
| } else if (adapter == ILabelProvider.class) { |
| return adapter.cast(new LabelProvider() { |
| @Override |
| public Image getImage(Object element) { |
| return AdtPlugin.getAndroidLogo(); |
| } |
| |
| @Override |
| public String getText(Object element) { |
| return ((IContentProposal) element).getLabel(); |
| } |
| }); |
| } |
| return super.getAdapter(adapter); |
| } |
| |
| @Override |
| public boolean isModified() throws Exception { |
| Object s = null; |
| try { |
| Element element = (Element) mNode.getXmlNode(); |
| if (element == null) { |
| return false; |
| } |
| String name = mDescriptor.getXmlLocalName(); |
| String uri = mDescriptor.getNamespaceUri(); |
| if (uri != null) { |
| return element.hasAttributeNS(uri, name); |
| } else { |
| return element.hasAttribute(name); |
| } |
| } catch (Exception e) { |
| // pass |
| } |
| return s != null && s.toString().length() > 0; |
| } |
| |
| @Nullable |
| public String getStringValue() { |
| Element element = (Element) mNode.getXmlNode(); |
| if (element == null) { |
| return null; |
| } |
| String name = mDescriptor.getXmlLocalName(); |
| String uri = mDescriptor.getNamespaceUri(); |
| Attr attr; |
| if (uri != null) { |
| attr = element.getAttributeNodeNS(uri, name); |
| } else { |
| attr = element.getAttributeNode(name); |
| } |
| if (attr != null) { |
| return attr.getValue(); |
| } |
| |
| Object viewObject = getFactory().getCurrentViewObject(); |
| if (viewObject != null) { |
| GraphicalEditorPart graphicalEditor = getGraphicalEditor(); |
| if (graphicalEditor == null) { |
| return null; |
| } |
| ViewHierarchy views = graphicalEditor.getCanvasControl().getViewHierarchy(); |
| Map<String, String> defaultProperties = views.getDefaultProperties(viewObject); |
| if (defaultProperties != null) { |
| return defaultProperties.get(name); |
| } |
| } |
| |
| return null; |
| } |
| |
| @Override |
| @Nullable |
| public Object getValue() throws Exception { |
| return getStringValue(); |
| } |
| |
| @Override |
| public void setValue(Object value) throws Exception { |
| CommonXmlEditor editor = getXmlEditor(); |
| if (editor == null) { |
| return; |
| } |
| final String attribute = mDescriptor.getXmlLocalName(); |
| final String xmlValue = value != null && value != UNKNOWN_VALUE ? value.toString() : null; |
| editor.wrapUndoEditXmlModel( |
| String.format("Set \"%1$s\" to \"%2$s\"", attribute, xmlValue), |
| new Runnable() { |
| @Override |
| public void run() { |
| mNode.setAttributeValue(attribute, |
| mDescriptor.getNamespaceUri(), xmlValue, true /*override*/); |
| mNode.commitDirtyAttributesToXml(); |
| } |
| }); |
| } |
| |
| @Override |
| @NonNull |
| public Property getComposite(Property[] properties) { |
| return XmlPropertyComposite.create(properties); |
| } |
| |
| @Nullable |
| GraphicalEditorPart getGraphicalEditor() { |
| return mFactory.getGraphicalEditor(); |
| } |
| |
| @Nullable |
| CommonXmlEditor getXmlEditor() { |
| GraphicalEditorPart graphicalEditor = getGraphicalEditor(); |
| if (graphicalEditor != null) { |
| return graphicalEditor.getEditorDelegate().getEditor(); |
| } |
| |
| return null; |
| } |
| |
| @Nullable |
| public Property getParent() { |
| return mParent; |
| } |
| |
| public void setParent(@Nullable Property parent) { |
| mParent = parent; |
| } |
| |
| @Override |
| public String toString() { |
| return getName() + ":" + getPriority(); |
| } |
| } |