diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties')
13 files changed, 0 insertions, 3297 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/BooleanXmlPropertyEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/BooleanXmlPropertyEditor.java deleted file mode 100644 index d6ff4d51d..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/BooleanXmlPropertyEditor.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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.VALUE_FALSE; -import static com.android.SdkConstants.VALUE_TRUE; - -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.Point; -import org.eclipse.wb.internal.core.DesignerPlugin; -import org.eclipse.wb.internal.core.model.property.Property; -import org.eclipse.wb.internal.core.model.property.table.PropertyTable; -import org.eclipse.wb.internal.core.utils.ui.DrawUtils; - -/** - * Handle an XML property which represents booleans. - * - * Similar to the WindowBuilder PropertyEditor, but operates on Strings rather - * than Booleans (which means it is a tri-state boolean: true, false, not set) - */ -public class BooleanXmlPropertyEditor extends XmlPropertyEditor { - public static final BooleanXmlPropertyEditor INSTANCE = new BooleanXmlPropertyEditor(); - - private static final Image mTrueImage = DesignerPlugin.getImage("properties/true.png"); - private static final Image mFalseImage = DesignerPlugin.getImage("properties/false.png"); - private static final Image mNullImage = - DesignerPlugin.getImage("properties/BooleanNull.png"); - private static final Image mUnknownImage = - DesignerPlugin.getImage("properties/BooleanUnknown.png"); - - private BooleanXmlPropertyEditor() { - } - - @Override - public void paint(Property property, GC gc, int x, int y, int width, int height) - throws Exception { - Object value = property.getValue(); - assert value == null || value instanceof String; - if (value == null || value instanceof String) { - String text = (String) value; - Image image; - if (VALUE_TRUE.equals(text)) { - image = mTrueImage; - } else if (VALUE_FALSE.equals(text)) { - image = mFalseImage; - } else if (text == null) { - image = mNullImage; - } else { - // Probably something like a reference, e.g. @boolean/foo - image = mUnknownImage; - } - - // draw image - DrawUtils.drawImageCV(gc, image, x, y, height); - - // prepare new position/width - int imageWidth = image.getBounds().width + 2; - width -= imageWidth; - - // draw text - if (text != null) { - x += imageWidth; - DrawUtils.drawStringCV(gc, text, x, y, width, height); - } - } - } - - @Override - public boolean activate(PropertyTable propertyTable, Property property, Point location) - throws Exception { - // check that user clicked on image - if (location == null || location.x < mTrueImage.getBounds().width + 2) { - cycleValue(property); - } - // don't activate - return false; - } - - @Override - public void doubleClick(Property property, Point location) throws Exception { - cycleValue(property); - } - - /** - * Cycles through the values - */ - private void cycleValue(Property property) throws Exception { - Object value = property.getValue(); - if (value == null || value instanceof String) { - // Cycle null => true => false => null - String text = (String) value; - if (VALUE_TRUE.equals(text)) { - property.setValue(VALUE_FALSE); - } else if (VALUE_FALSE.equals(text)) { - property.setValue(null); - } else { - property.setValue(VALUE_TRUE); - } - } else { - assert false; - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/EnumXmlPropertyEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/EnumXmlPropertyEditor.java deleted file mode 100644 index f1a3f2aaa..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/EnumXmlPropertyEditor.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor; -import com.android.ide.eclipse.adt.internal.editors.descriptors.ListAttributeDescriptor; - -import org.eclipse.wb.core.controls.CCombo3; -import org.eclipse.wb.internal.core.model.property.Property; -import org.eclipse.wb.internal.core.model.property.editor.AbstractComboPropertyEditor; -import org.eclipse.wb.internal.core.model.property.editor.ITextValuePropertyEditor; - -class EnumXmlPropertyEditor extends AbstractComboPropertyEditor implements - ITextValuePropertyEditor { - public static final EnumXmlPropertyEditor INSTANCE = new EnumXmlPropertyEditor(); - - private EnumXmlPropertyEditor() { - } - - @Override - protected String getText(Property property) throws Exception { - Object value = property.getValue(); - if (value == null) { - return ""; - } else if (value instanceof String) { - return (String) value; - } else if (value == Property.UNKNOWN_VALUE) { - return "<varies>"; - } else { - return ""; - } - } - - private String[] getItems(Property property) { - XmlProperty xmlProperty = (XmlProperty) property; - AttributeDescriptor descriptor = xmlProperty.getDescriptor(); - assert descriptor instanceof ListAttributeDescriptor; - ListAttributeDescriptor list = (ListAttributeDescriptor) descriptor; - return list.getValues(); - } - - @Override - protected void addItems(Property property, CCombo3 combo) throws Exception { - for (String item : getItems(property)) { - combo.add(item); - } - } - - @Override - protected void selectItem(Property property, CCombo3 combo) throws Exception { - combo.setText(getText(property)); - } - - @Override - protected void toPropertyEx(Property property, CCombo3 combo, int index) throws Exception { - property.setValue(getItems(property)[index]); - } - - @Override - public void setText(Property property, String text) throws Exception { - property.setValue(text); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/FlagXmlPropertyDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/FlagXmlPropertyDialog.java deleted file mode 100644 index 5e1e7029f..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/FlagXmlPropertyDialog.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * 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 com.android.annotations.NonNull; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.google.common.base.Splitter; - -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.viewers.CheckStateChangedEvent; -import org.eclipse.jface.viewers.CheckboxTableViewer; -import org.eclipse.jface.viewers.ICheckStateListener; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.KeyListener; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableItem; -import org.eclipse.wb.internal.core.utils.execution.ExecutionUtils; -import org.eclipse.wb.internal.core.utils.execution.RunnableEx; -import org.eclipse.wb.internal.core.utils.ui.dialogs.ResizableDialog; - -import java.util.ArrayList; -import java.util.List; - -class FlagXmlPropertyDialog extends ResizableDialog -implements IStructuredContentProvider, ICheckStateListener, SelectionListener, KeyListener { - private final String mTitle; - private final XmlProperty mProperty; - private final String[] mFlags; - private final boolean mIsRadio; - - private Table mTable; - private CheckboxTableViewer mViewer; - - FlagXmlPropertyDialog( - @NonNull Shell parentShell, - @NonNull String title, - boolean isRadio, - @NonNull String[] flags, - @NonNull XmlProperty property) { - super(parentShell, AdtPlugin.getDefault()); - mTitle = title; - mIsRadio = isRadio; - mFlags = flags; - mProperty = property; - } - - @Override - protected void configureShell(Shell newShell) { - super.configureShell(newShell); - newShell.setText(mTitle); - } - - @Override - protected Control createDialogArea(Composite parent) { - Composite container = (Composite) super.createDialogArea(parent); - - mViewer = CheckboxTableViewer.newCheckList(container, - SWT.BORDER | SWT.FULL_SELECTION | SWT.HIDE_SELECTION); - mTable = mViewer.getTable(); - mTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); - - Composite workaround = PropertyFactory.addWorkaround(container); - if (workaround != null) { - workaround.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1)); - } - - mViewer.setContentProvider(this); - mViewer.setInput(mFlags); - - String current = mProperty.getStringValue(); - if (current != null) { - Object[] checked = null; - if (mIsRadio) { - checked = new String[] { current }; - } else { - List<String> flags = new ArrayList<String>(); - for (String s : Splitter.on('|').omitEmptyStrings().trimResults().split(current)) { - flags.add(s); - } - checked = flags.toArray(new String[flags.size()]); - } - mViewer.setCheckedElements(checked); - } - if (mFlags.length > 0) { - mTable.setSelection(0); - } - - if (mIsRadio) { - // Enforce single-item selection - mViewer.addCheckStateListener(this); - } - mTable.addSelectionListener(this); - mTable.addKeyListener(this); - - return container; - } - - @Override - protected void createButtonsForButtonBar(Composite parent) { - createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); - createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); - } - - @Override - protected Point getDefaultSize() { - return new Point(450, 400); - } - - @Override - protected void okPressed() { - // Apply the value - ExecutionUtils.runLog(new RunnableEx() { - @Override - public void run() throws Exception { - StringBuilder sb = new StringBuilder(30); - for (Object o : mViewer.getCheckedElements()) { - if (sb.length() > 0) { - sb.append('|'); - } - sb.append((String) o); - } - String value = sb.length() > 0 ? sb.toString() : null; - mProperty.setValue(value); - } - }); - - // close dialog - super.okPressed(); - } - - // ---- Implements IStructuredContentProvider ---- - - @Override - public Object[] getElements(Object inputElement) { - return (Object []) inputElement; - } - - @Override - public void dispose() { - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - } - - // ---- Implements ICheckStateListener ---- - - @Override - public void checkStateChanged(CheckStateChangedEvent event) { - // Try to disable other elements that conflict with this - boolean isChecked = event.getChecked(); - if (isChecked) { - Object selected = event.getElement(); - for (Object other : mViewer.getCheckedElements()) { - if (other != selected) { - mViewer.setChecked(other, false); - } - } - } else { - - } - } - - // ---- Implements SelectionListener ---- - - @Override - public void widgetSelected(SelectionEvent e) { - } - - @Override - public void widgetDefaultSelected(SelectionEvent e) { - if (e.item instanceof TableItem) { - TableItem item = (TableItem) e.item; - item.setChecked(!item.getChecked()); - } - } - - // ---- Implements KeyListener ---- - - @Override - public void keyPressed(KeyEvent e) { - // Let space toggle checked state - if (e.keyCode == ' ' /* SWT.SPACE requires Eclipse 3.7 */) { - if (mTable.getSelectionCount() == 1) { - TableItem item = mTable.getSelection()[0]; - item.setChecked(!item.getChecked()); - } - } - } - - @Override - public void keyReleased(KeyEvent e) { - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/PropertyFactory.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/PropertyFactory.java deleted file mode 100644 index 2b8cfbf43..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/PropertyFactory.java +++ /dev/null @@ -1,750 +0,0 @@ -/* - * 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_ID; -import static com.android.SdkConstants.ATTR_LAYOUT_MARGIN; -import static com.android.SdkConstants.ATTR_LAYOUT_RESOURCE_PREFIX; - -import com.android.annotations.Nullable; -import com.android.ide.common.api.IAttributeInfo; -import com.android.ide.common.api.IAttributeInfo.Format; -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.SeparatorAttributeDescriptor; -import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor; -import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart; -import com.android.ide.eclipse.adt.internal.editors.layout.gre.ViewMetadataRepository; -import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode; -import com.android.tools.lint.detector.api.LintUtils; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; - -import org.eclipse.jface.dialogs.MessageDialog; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Link; -import org.eclipse.ui.IWorkbench; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.browser.IWebBrowser; -import org.eclipse.wb.internal.core.editor.structure.property.PropertyListIntersector; -import org.eclipse.wb.internal.core.model.property.ComplexProperty; -import org.eclipse.wb.internal.core.model.property.Property; -import org.eclipse.wb.internal.core.model.property.category.PropertyCategory; -import org.eclipse.wb.internal.core.model.property.editor.PropertyEditor; -import org.eclipse.wb.internal.core.model.property.editor.presentation.ButtonPropertyEditorPresentation; - -import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; - -/** - * The {@link PropertyFactory} creates (and caches) the set of {@link Property} - * instances applicable to a given node. It's also responsible for ordering - * these, and sometimes combining them into {@link ComplexProperty} category - * nodes. - * <p> - * TODO: For any properties that are *set* in XML, they should NOT be labeled as - * advanced (which would make them disappear) - */ -public class PropertyFactory { - /** Disable cache during development only */ - @SuppressWarnings("unused") - private static final boolean CACHE_ENABLED = true || !LintUtils.assertionsEnabled(); - static { - if (!CACHE_ENABLED) { - System.err.println("WARNING: The property cache is disabled"); - } - } - - private static final Property[] NO_PROPERTIES = new Property[0]; - - private static final int PRIO_FIRST = -100000; - private static final int PRIO_SECOND = PRIO_FIRST + 10; - private static final int PRIO_LAST = 100000; - - private final GraphicalEditorPart mGraphicalEditorPart; - private Map<UiViewElementNode, Property[]> mCache = - new WeakHashMap<UiViewElementNode, Property[]>(); - private UiViewElementNode mCurrentViewCookie; - - /** Sorting orders for the properties */ - public enum SortingMode { - NATURAL, - BY_ORIGIN, - ALPHABETICAL; - } - - /** The default sorting mode */ - public static final SortingMode DEFAULT_MODE = SortingMode.BY_ORIGIN; - - private SortingMode mSortMode = DEFAULT_MODE; - private SortingMode mCacheSortMode; - - public PropertyFactory(GraphicalEditorPart graphicalEditorPart) { - mGraphicalEditorPart = graphicalEditorPart; - } - - /** - * Get the properties for the given list of selection items. - * - * @param items the {@link CanvasViewInfo} instances to get an intersected - * property list for - * @return the properties for the given items - */ - public Property[] getProperties(List<CanvasViewInfo> items) { - mCurrentViewCookie = null; - - if (items == null || items.size() == 0) { - return NO_PROPERTIES; - } else if (items.size() == 1) { - CanvasViewInfo item = items.get(0); - mCurrentViewCookie = item.getUiViewNode(); - - return getProperties(item); - } else { - // intersect properties - PropertyListIntersector intersector = new PropertyListIntersector(); - for (CanvasViewInfo node : items) { - intersector.intersect(getProperties(node)); - } - - return intersector.getProperties(); - } - } - - private Property[] getProperties(CanvasViewInfo item) { - UiViewElementNode node = item.getUiViewNode(); - if (node == null) { - return NO_PROPERTIES; - } - - if (mCacheSortMode != mSortMode) { - mCacheSortMode = mSortMode; - mCache.clear(); - } - - Property[] properties = mCache.get(node); - if (!CACHE_ENABLED) { - properties = null; - } - if (properties == null) { - Collection<? extends Property> propertyList = getProperties(node); - if (propertyList == null) { - properties = new Property[0]; - } else { - properties = propertyList.toArray(new Property[propertyList.size()]); - } - mCache.put(node, properties); - } - return properties; - } - - - protected Collection<? extends Property> getProperties(UiViewElementNode node) { - ViewMetadataRepository repository = ViewMetadataRepository.get(); - ViewElementDescriptor viewDescriptor = (ViewElementDescriptor) node.getDescriptor(); - String fqcn = viewDescriptor.getFullClassName(); - Set<String> top = new HashSet<String>(repository.getTopAttributes(fqcn)); - AttributeDescriptor[] attributeDescriptors = node.getAttributeDescriptors(); - - List<XmlProperty> properties = new ArrayList<XmlProperty>(attributeDescriptors.length); - int priority = 0; - for (final AttributeDescriptor descriptor : attributeDescriptors) { - // TODO: Filter out non-public properties!! - // (They shouldn't be in the descriptors at all) - - assert !(descriptor instanceof SeparatorAttributeDescriptor); // No longer inserted - if (descriptor instanceof XmlnsAttributeDescriptor) { - continue; - } - - PropertyEditor editor = XmlPropertyEditor.INSTANCE; - IAttributeInfo info = descriptor.getAttributeInfo(); - if (info != null) { - EnumSet<Format> formats = info.getFormats(); - if (formats.contains(Format.BOOLEAN)) { - editor = BooleanXmlPropertyEditor.INSTANCE; - } else if (formats.contains(Format.ENUM)) { - // We deliberately don't use EnumXmlPropertyEditor.INSTANCE here, - // since some attributes (such as layout_width) can have not just one - // of the enum values but custom values such as "42dp" as well. And - // furthermore, we don't even bother limiting this to formats.size()==1, - // since the editing experience with the enum property editor is - // more limited than the text editor plus enum completer anyway - // (for example, you can't type to filter the values, and clearing - // the value is harder.) - } - } - - XmlProperty property = new XmlProperty(editor, this, node, descriptor); - // Assign ids sequentially. This ensures that the properties will mostly keep their - // relative order (such as placing width before height), even though we will regroup - // some (such as properties in the same category, and the layout params etc) - priority += 10; - - PropertyCategory category = PropertyCategory.NORMAL; - String name = descriptor.getXmlLocalName(); - if (top.contains(name) || PropertyMetadata.isPreferred(name)) { - category = PropertyCategory.PREFERRED; - property.setPriority(PRIO_FIRST + priority); - } else { - property.setPriority(priority); - - // Prefer attributes defined on the specific type of this - // widget - // NOTE: This doesn't work very well for TextViews - /* IAttributeInfo attributeInfo = descriptor.getAttributeInfo(); - if (attributeInfo != null && fqcn.equals(attributeInfo.getDefinedBy())) { - category = PropertyCategory.PREFERRED; - } else*/ if (PropertyMetadata.isAdvanced(name)) { - category = PropertyCategory.ADVANCED; - } - } - if (category != null) { - property.setCategory(category); - } - properties.add(property); - } - - switch (mSortMode) { - case BY_ORIGIN: - return sortByOrigin(node, properties); - - case ALPHABETICAL: - return sortAlphabetically(node, properties); - - default: - case NATURAL: - return sortNatural(node, properties); - } - } - - protected Collection<? extends Property> sortAlphabetically( - UiViewElementNode node, - List<XmlProperty> properties) { - Collections.sort(properties, Property.ALPHABETICAL); - return properties; - } - - protected Collection<? extends Property> sortByOrigin( - UiViewElementNode node, - List<XmlProperty> properties) { - List<Property> collapsed = new ArrayList<Property>(properties.size()); - List<Property> layoutProperties = Lists.newArrayListWithExpectedSize(20); - List<Property> marginProperties = null; - List<Property> deprecatedProperties = null; - Map<String, ComplexProperty> categoryToProperty = new HashMap<String, ComplexProperty>(); - Multimap<String, Property> categoryToProperties = ArrayListMultimap.create(); - - if (properties.isEmpty()) { - return properties; - } - - ViewElementDescriptor parent = (ViewElementDescriptor) properties.get(0).getDescriptor() - .getParent(); - Map<String, Integer> categoryPriorities = Maps.newHashMap(); - int nextCategoryPriority = 100; - while (parent != null) { - categoryPriorities.put(parent.getFullClassName(), nextCategoryPriority += 100); - parent = parent.getSuperClassDesc(); - } - - for (int i = 0, max = properties.size(); i < max; i++) { - XmlProperty property = properties.get(i); - - AttributeDescriptor descriptor = property.getDescriptor(); - if (descriptor.isDeprecated()) { - if (deprecatedProperties == null) { - deprecatedProperties = Lists.newArrayListWithExpectedSize(10); - } - deprecatedProperties.add(property); - continue; - } - - String firstName = descriptor.getXmlLocalName(); - if (firstName.startsWith(ATTR_LAYOUT_RESOURCE_PREFIX)) { - if (firstName.startsWith(ATTR_LAYOUT_MARGIN)) { - if (marginProperties == null) { - marginProperties = Lists.newArrayListWithExpectedSize(5); - } - marginProperties.add(property); - } else { - layoutProperties.add(property); - } - continue; - } - - if (firstName.equals(ATTR_ID)) { - // Add id to the front (though the layout parameters will be added to - // the front of this at the end) - property.setPriority(PRIO_FIRST); - collapsed.add(property); - continue; - } - - if (property.getCategory() == PropertyCategory.PREFERRED) { - collapsed.add(property); - // Fall through: these are *duplicated* inside their defining categories! - // However, create a new instance of the property, such that the propertysheet - // doesn't see the same property instance twice (when selected, it will highlight - // both, etc.) Also, set the category to Normal such that we don't draw attention - // to it again. We want it to appear in both places such that somebody looking - // within a category will always find it there, even if for this specific - // view type it's a common attribute and replicated up at the top. - XmlProperty oldProperty = property; - property = new XmlProperty(oldProperty.getEditor(), this, node, - oldProperty.getDescriptor()); - property.setPriority(oldProperty.getPriority()); - } - - IAttributeInfo attributeInfo = descriptor.getAttributeInfo(); - if (attributeInfo != null && attributeInfo.getDefinedBy() != null) { - String category = attributeInfo.getDefinedBy(); - ComplexProperty complex = categoryToProperty.get(category); - if (complex == null) { - complex = new ComplexProperty( - category.substring(category.lastIndexOf('.') + 1), - "[]", - null /* properties */); - categoryToProperty.put(category, complex); - Integer categoryPriority = categoryPriorities.get(category); - if (categoryPriority != null) { - complex.setPriority(categoryPriority); - } else { - // Descriptor for an attribute whose definedBy does *not* - // correspond to one of the known superclasses of this widget. - // This sometimes happens; for example, a RatingBar will pull in - // an ImageView's minWidth attribute. Probably an error in the - // metadata, but deal with it gracefully here. - categoryPriorities.put(category, nextCategoryPriority += 100); - complex.setPriority(nextCategoryPriority); - } - } - categoryToProperties.put(category, property); - continue; - } else { - collapsed.add(property); - } - } - - // Update the complex properties - for (String category : categoryToProperties.keySet()) { - Collection<Property> subProperties = categoryToProperties.get(category); - if (subProperties.size() > 1) { - ComplexProperty complex = categoryToProperty.get(category); - assert complex != null : category; - Property[] subArray = new Property[subProperties.size()]; - complex.setProperties(subProperties.toArray(subArray)); - //complex.setPriority(subArray[0].getPriority()); - - collapsed.add(complex); - - boolean allAdvanced = true; - boolean isPreferred = false; - for (Property p : subProperties) { - PropertyCategory c = p.getCategory(); - if (c != PropertyCategory.ADVANCED) { - allAdvanced = false; - } - if (c == PropertyCategory.PREFERRED) { - isPreferred = true; - } - } - if (isPreferred) { - complex.setCategory(PropertyCategory.PREFERRED); - } else if (allAdvanced) { - complex.setCategory(PropertyCategory.ADVANCED); - } - } else if (subProperties.size() == 1) { - collapsed.add(subProperties.iterator().next()); - } - } - - if (layoutProperties.size() > 0 || marginProperties != null) { - if (marginProperties != null) { - XmlProperty[] m = - marginProperties.toArray(new XmlProperty[marginProperties.size()]); - Property marginProperty = new ComplexProperty( - "Margins", - "[]", - m); - layoutProperties.add(marginProperty); - marginProperty.setPriority(PRIO_LAST); - - for (XmlProperty p : m) { - p.setParent(marginProperty); - } - } - Property[] l = layoutProperties.toArray(new Property[layoutProperties.size()]); - Arrays.sort(l, Property.PRIORITY); - Property property = new ComplexProperty( - "Layout Parameters", - "[]", - l); - for (Property p : l) { - if (p instanceof XmlProperty) { - ((XmlProperty) p).setParent(property); - } - } - property.setCategory(PropertyCategory.PREFERRED); - collapsed.add(property); - property.setPriority(PRIO_SECOND); - } - - if (deprecatedProperties != null && deprecatedProperties.size() > 0) { - Property property = new ComplexProperty( - "Deprecated", - "(Deprecated Properties)", - deprecatedProperties.toArray(new Property[deprecatedProperties.size()])); - property.setPriority(PRIO_LAST); - collapsed.add(property); - } - - Collections.sort(collapsed, Property.PRIORITY); - - return collapsed; - } - - protected Collection<? extends Property> sortNatural( - UiViewElementNode node, - List<XmlProperty> properties) { - Collections.sort(properties, Property.ALPHABETICAL); - List<Property> collapsed = new ArrayList<Property>(properties.size()); - List<Property> layoutProperties = Lists.newArrayListWithExpectedSize(20); - List<Property> marginProperties = null; - List<Property> deprecatedProperties = null; - Map<String, ComplexProperty> categoryToProperty = new HashMap<String, ComplexProperty>(); - Multimap<String, Property> categoryToProperties = ArrayListMultimap.create(); - - for (int i = 0, max = properties.size(); i < max; i++) { - XmlProperty property = properties.get(i); - - AttributeDescriptor descriptor = property.getDescriptor(); - if (descriptor.isDeprecated()) { - if (deprecatedProperties == null) { - deprecatedProperties = Lists.newArrayListWithExpectedSize(10); - } - deprecatedProperties.add(property); - continue; - } - - String firstName = descriptor.getXmlLocalName(); - if (firstName.startsWith(ATTR_LAYOUT_RESOURCE_PREFIX)) { - if (firstName.startsWith(ATTR_LAYOUT_MARGIN)) { - if (marginProperties == null) { - marginProperties = Lists.newArrayListWithExpectedSize(5); - } - marginProperties.add(property); - } else { - layoutProperties.add(property); - } - continue; - } - - if (firstName.equals(ATTR_ID)) { - // Add id to the front (though the layout parameters will be added to - // the front of this at the end) - property.setPriority(PRIO_FIRST); - collapsed.add(property); - continue; - } - - String category = PropertyMetadata.getCategory(firstName); - if (category != null) { - ComplexProperty complex = categoryToProperty.get(category); - if (complex == null) { - complex = new ComplexProperty( - category, - "[]", - null /* properties */); - categoryToProperty.put(category, complex); - complex.setPriority(property.getPriority()); - } - categoryToProperties.put(category, property); - continue; - } - - // Index of second word in the first name, so in fooBar it's 3 (index of 'B') - int firstNameIndex = firstName.length(); - for (int k = 0, kn = firstName.length(); k < kn; k++) { - if (Character.isUpperCase(firstName.charAt(k))) { - firstNameIndex = k; - break; - } - } - - // Scout forwards and see how many properties we can combine - int j = i + 1; - if (property.getCategory() != PropertyCategory.PREFERRED - && !property.getDescriptor().isDeprecated()) { - for (; j < max; j++) { - XmlProperty next = properties.get(j); - String nextName = next.getName(); - if (nextName.regionMatches(0, firstName, 0, firstNameIndex) - // Also make sure we begin the second word at the next - // character; if not, we could have something like - // scrollBar - // scrollingBehavior - && nextName.length() > firstNameIndex - && Character.isUpperCase(nextName.charAt(firstNameIndex))) { - - // Deprecated attributes, and preferred attributes, should not - // be pushed into normal clusters (preferred stay top-level - // and sort to the top, deprecated are all put in the same cluster at - // the end) - - if (next.getCategory() == PropertyCategory.PREFERRED) { - break; - } - if (next.getDescriptor().isDeprecated()) { - break; - } - - // This property should be combined with the previous - // property - } else { - break; - } - } - } - if (j - i > 1) { - // Combining multiple properties: all the properties from i - // through j inclusive - XmlProperty[] subprops = new XmlProperty[j - i]; - for (int k = i, index = 0; k < j; k++, index++) { - subprops[index] = properties.get(k); - } - Arrays.sort(subprops, Property.PRIORITY); - - // See if we can compute a LONGER base than just the first word. - // For example, if we have "lineSpacingExtra" and "lineSpacingMultiplier" - // we'd like the base to be "lineSpacing", not "line". - int common = firstNameIndex; - for (int k = firstNameIndex + 1, n = firstName.length(); k < n; k++) { - if (Character.isUpperCase(firstName.charAt(k))) { - common = k; - break; - } - } - if (common > firstNameIndex) { - for (int k = 0, n = subprops.length; k < n; k++) { - String nextName = subprops[k].getName(); - if (nextName.regionMatches(0, firstName, 0, common) - // Also make sure we begin the second word at the next - // character; if not, we could have something like - // scrollBar - // scrollingBehavior - && nextName.length() > common - && Character.isUpperCase(nextName.charAt(common))) { - // New prefix is okay - } else { - common = firstNameIndex; - break; - } - } - firstNameIndex = common; - } - - String base = firstName.substring(0, firstNameIndex); - base = DescriptorsUtils.capitalize(base); - Property complexProperty = new ComplexProperty( - base, - "[]", - subprops); - complexProperty.setPriority(subprops[0].getPriority()); - //complexProperty.setCategory(PropertyCategory.PREFERRED); - collapsed.add(complexProperty); - boolean allAdvanced = true; - boolean isPreferred = false; - for (XmlProperty p : subprops) { - p.setParent(complexProperty); - PropertyCategory c = p.getCategory(); - if (c != PropertyCategory.ADVANCED) { - allAdvanced = false; - } - if (c == PropertyCategory.PREFERRED) { - isPreferred = true; - } - } - if (isPreferred) { - complexProperty.setCategory(PropertyCategory.PREFERRED); - } else if (allAdvanced) { - complexProperty.setCategory(PropertyCategory.PREFERRED); - } - } else { - // Add the individual properties (usually 1, sometimes 2 - for (int k = i; k < j; k++) { - collapsed.add(properties.get(k)); - } - } - - i = j - 1; // -1: compensate in advance for the for-loop adding 1 - } - - // Update the complex properties - for (String category : categoryToProperties.keySet()) { - Collection<Property> subProperties = categoryToProperties.get(category); - if (subProperties.size() > 1) { - ComplexProperty complex = categoryToProperty.get(category); - assert complex != null : category; - Property[] subArray = new Property[subProperties.size()]; - complex.setProperties(subProperties.toArray(subArray)); - complex.setPriority(subArray[0].getPriority()); - collapsed.add(complex); - - boolean allAdvanced = true; - boolean isPreferred = false; - for (Property p : subProperties) { - PropertyCategory c = p.getCategory(); - if (c != PropertyCategory.ADVANCED) { - allAdvanced = false; - } - if (c == PropertyCategory.PREFERRED) { - isPreferred = true; - } - } - if (isPreferred) { - complex.setCategory(PropertyCategory.PREFERRED); - } else if (allAdvanced) { - complex.setCategory(PropertyCategory.ADVANCED); - } - } else if (subProperties.size() == 1) { - collapsed.add(subProperties.iterator().next()); - } - } - - if (layoutProperties.size() > 0 || marginProperties != null) { - if (marginProperties != null) { - XmlProperty[] m = - marginProperties.toArray(new XmlProperty[marginProperties.size()]); - Property marginProperty = new ComplexProperty( - "Margins", - "[]", - m); - layoutProperties.add(marginProperty); - marginProperty.setPriority(PRIO_LAST); - - for (XmlProperty p : m) { - p.setParent(marginProperty); - } - } - Property[] l = layoutProperties.toArray(new Property[layoutProperties.size()]); - Arrays.sort(l, Property.PRIORITY); - Property property = new ComplexProperty( - "Layout Parameters", - "[]", - l); - for (Property p : l) { - if (p instanceof XmlProperty) { - ((XmlProperty) p).setParent(property); - } - } - property.setCategory(PropertyCategory.PREFERRED); - collapsed.add(property); - property.setPriority(PRIO_SECOND); - } - - if (deprecatedProperties != null && deprecatedProperties.size() > 0) { - Property property = new ComplexProperty( - "Deprecated", - "(Deprecated Properties)", - deprecatedProperties.toArray(new Property[deprecatedProperties.size()])); - property.setPriority(PRIO_LAST); - collapsed.add(property); - } - - Collections.sort(collapsed, Property.PRIORITY); - - return collapsed; - } - - @Nullable - GraphicalEditorPart getGraphicalEditor() { - return mGraphicalEditorPart; - } - - // HACK: This should be passed into each property instead - public Object getCurrentViewObject() { - return mCurrentViewCookie; - } - - public void setSortingMode(SortingMode sortingMode) { - mSortMode = sortingMode; - } - - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=388574 - public static Composite addWorkaround(Composite parent) { - if (ButtonPropertyEditorPresentation.isInWorkaround) { - Composite top = new Composite(parent, SWT.NONE); - top.setLayout(new GridLayout(1, false)); - Label label = new Label(top, SWT.WRAP); - label.setText( - "This dialog is shown instead of an inline text editor as a\n" + - "workaround for an Eclipse bug specific to OSX Mountain Lion.\n" + - "It should be fixed in Eclipse 4.3."); - label.setForeground(top.getDisplay().getSystemColor(SWT.COLOR_RED)); - GridData data = new GridData(); - data.grabExcessVerticalSpace = false; - data.grabExcessHorizontalSpace = false; - data.horizontalAlignment = GridData.FILL; - data.verticalAlignment = GridData.BEGINNING; - label.setLayoutData(data); - - Link link = new Link(top, SWT.NO_FOCUS); - link.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1)); - link.setText("<a>https://bugs.eclipse.org/bugs/show_bug.cgi?id=388574</a>"); - link.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent event) { - try { - IWorkbench workbench = PlatformUI.getWorkbench(); - IWebBrowser browser = workbench.getBrowserSupport().getExternalBrowser(); - browser.openURL(new URL(event.text)); - } catch (Exception e) { - String message = String.format( - "Could not open browser. Vist\n%1$s\ninstead.", - event.text); - MessageDialog.openError(((Link)event.getSource()).getShell(), - "Browser Error", message); - } - } - }); - - return top; - } - - return null; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/PropertyMetadata.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/PropertyMetadata.java deleted file mode 100644 index b230aa99d..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/PropertyMetadata.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * 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_CONTENT_DESCRIPTION; -import static com.android.SdkConstants.ATTR_HINT; -import static com.android.SdkConstants.ATTR_TEXT; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; - -import java.util.HashSet; -import java.util.Set; - -/** Extra metadata about properties not available from the descriptors (yet) */ -class PropertyMetadata { - static boolean isAdvanced(@NonNull String name) { - return sAdvanced.contains(name); - } - - static boolean isPreferred(@NonNull String name) { - return sPreferred.contains(name); - } - - @Nullable - static String getCategory(@NonNull String name) { - //return sCategories.get(name); - assert false : "Disabled to save memory since this method is not currently used."; - return null; - } - - private static final int ADVANCED_MAP_SIZE = 134; - private static final Set<String> sAdvanced = new HashSet<String>(ADVANCED_MAP_SIZE); - static { - // This metadata about which attributes are "advanced" was generated as follows: - // First, I ran the sdk/attribute_stats project with the --list argument to dump out - // *all* referenced XML attributes found in layouts, run against a bunch of - // sample Android code (development/samples, packages/apps, vendor, etc. - // - // Then I iterated over the LayoutDescriptors' ViewElementDescriptors' - // AttributeDescriptors, and basically diffed the two: any attribute descriptor name - // which was *not* found in any of the representative layouts is added here - // as an advanced property. - // - // Then I manually edited in some attributes that were referenced in the sample - // layouts but which I still consider to be advanced: - // -- nothing right now - - // I also manually *removed* some entries from the below list: - // drawableBottom (the others, drawableTop, drawableLeft and drawableRight were all - // NOT on the list so keep bottom off for symmetry) - // rating (useful when you deal with a RatingsBar component) - - - // Automatically generated, see above: - sAdvanced.add("alwaysDrawnWithCache"); - sAdvanced.add("animationCache"); - sAdvanced.add("animationDuration"); - sAdvanced.add("animationResolution"); - sAdvanced.add("baseline"); - sAdvanced.add("bufferType"); - sAdvanced.add("calendarViewShown"); - sAdvanced.add("completionHint"); - sAdvanced.add("completionHintView"); - sAdvanced.add("completionThreshold"); - sAdvanced.add("cursorVisible"); - sAdvanced.add("dateTextAppearance"); - sAdvanced.add("dial"); - sAdvanced.add("digits"); - sAdvanced.add("disableChildrenWhenDisabled"); - sAdvanced.add("disabledAlpha"); - sAdvanced.add("drawableAlpha"); - sAdvanced.add("drawableEnd"); - sAdvanced.add("drawableStart"); - sAdvanced.add("drawingCacheQuality"); - sAdvanced.add("dropDownAnchor"); - sAdvanced.add("dropDownHeight"); - sAdvanced.add("dropDownHorizontalOffset"); - sAdvanced.add("dropDownSelector"); - sAdvanced.add("dropDownVerticalOffset"); - sAdvanced.add("dropDownWidth"); - sAdvanced.add("editorExtras"); - sAdvanced.add("ems"); - sAdvanced.add("endYear"); - sAdvanced.add("eventsInterceptionEnabled"); - sAdvanced.add("fadeDuration"); - sAdvanced.add("fadeEnabled"); - sAdvanced.add("fadeOffset"); - sAdvanced.add("fadeScrollbars"); - sAdvanced.add("filterTouchesWhenObscured"); - sAdvanced.add("firstDayOfWeek"); - sAdvanced.add("flingable"); - sAdvanced.add("focusedMonthDateColor"); - sAdvanced.add("foregroundInsidePadding"); - sAdvanced.add("format"); - sAdvanced.add("gestureColor"); - sAdvanced.add("gestureStrokeAngleThreshold"); - sAdvanced.add("gestureStrokeLengthThreshold"); - sAdvanced.add("gestureStrokeSquarenessThreshold"); - sAdvanced.add("gestureStrokeType"); - sAdvanced.add("gestureStrokeWidth"); - sAdvanced.add("hand_hour"); - sAdvanced.add("hand_minute"); - sAdvanced.add("hapticFeedbackEnabled"); - sAdvanced.add("id"); - sAdvanced.add("imeActionId"); - sAdvanced.add("imeActionLabel"); - sAdvanced.add("indeterminateDrawable"); - sAdvanced.add("indeterminateDuration"); - sAdvanced.add("inputMethod"); - sAdvanced.add("interpolator"); - sAdvanced.add("isScrollContainer"); - sAdvanced.add("keepScreenOn"); - sAdvanced.add("layerType"); - sAdvanced.add("layoutDirection"); - sAdvanced.add("maxDate"); - sAdvanced.add("minDate"); - sAdvanced.add("mode"); - sAdvanced.add("numeric"); - sAdvanced.add("paddingEnd"); - sAdvanced.add("paddingStart"); - sAdvanced.add("persistentDrawingCache"); - sAdvanced.add("phoneNumber"); - sAdvanced.add("popupBackground"); - sAdvanced.add("popupPromptView"); - sAdvanced.add("privateImeOptions"); - sAdvanced.add("quickContactWindowSize"); - //sAdvanced.add("rating"); - sAdvanced.add("requiresFadingEdge"); - sAdvanced.add("rotation"); - sAdvanced.add("rotationX"); - sAdvanced.add("rotationY"); - sAdvanced.add("saveEnabled"); - sAdvanced.add("scaleX"); - sAdvanced.add("scaleY"); - sAdvanced.add("scrollX"); - sAdvanced.add("scrollY"); - sAdvanced.add("scrollbarAlwaysDrawHorizontalTrack"); - sAdvanced.add("scrollbarDefaultDelayBeforeFade"); - sAdvanced.add("scrollbarFadeDuration"); - sAdvanced.add("scrollbarSize"); - sAdvanced.add("scrollbarThumbHorizontal"); - sAdvanced.add("scrollbarThumbVertical"); - sAdvanced.add("scrollbarTrackHorizontal"); - sAdvanced.add("scrollbarTrackVertical"); - sAdvanced.add("secondaryProgress"); - sAdvanced.add("selectedDateVerticalBar"); - sAdvanced.add("selectedWeekBackgroundColor"); - sAdvanced.add("selectionDivider"); - sAdvanced.add("selectionDividerHeight"); - sAdvanced.add("showWeekNumber"); - sAdvanced.add("shownWeekCount"); - sAdvanced.add("solidColor"); - sAdvanced.add("soundEffectsEnabled"); - sAdvanced.add("spinnerMode"); - sAdvanced.add("spinnersShown"); - sAdvanced.add("startYear"); - sAdvanced.add("switchMinWidth"); - sAdvanced.add("switchPadding"); - sAdvanced.add("switchTextAppearance"); - sAdvanced.add("textColorHighlight"); - sAdvanced.add("textCursorDrawable"); - sAdvanced.add("textDirection"); - sAdvanced.add("textEditNoPasteWindowLayout"); - sAdvanced.add("textEditPasteWindowLayout"); - sAdvanced.add("textEditSideNoPasteWindowLayout"); - sAdvanced.add("textEditSidePasteWindowLayout"); - sAdvanced.add("textEditSuggestionItemLayout"); - sAdvanced.add("textIsSelectable"); - sAdvanced.add("textOff"); - sAdvanced.add("textOn"); - sAdvanced.add("textScaleX"); - sAdvanced.add("textSelectHandle"); - sAdvanced.add("textSelectHandleLeft"); - sAdvanced.add("textSelectHandleRight"); - sAdvanced.add("thumbOffset"); - sAdvanced.add("thumbTextPadding"); - sAdvanced.add("tint"); - sAdvanced.add("track"); - sAdvanced.add("transformPivotX"); - sAdvanced.add("transformPivotY"); - sAdvanced.add("translationX"); - sAdvanced.add("translationY"); - sAdvanced.add("uncertainGestureColor"); - sAdvanced.add("unfocusedMonthDateColor"); - sAdvanced.add("unselectedAlpha"); - sAdvanced.add("verticalScrollbarPosition"); - sAdvanced.add("weekDayTextAppearance"); - sAdvanced.add("weekNumberColor"); - sAdvanced.add("weekSeparatorLineColor"); - - assert sAdvanced.size() == ADVANCED_MAP_SIZE : sAdvanced.size(); - - } - - private static final int PREFERRED_MAP_SIZE = 7; - private static final Set<String> sPreferred = new HashSet<String>(PREFERRED_MAP_SIZE); - static { - // Manual registrations of attributes that should be treated as preferred if - // they are available on a widget even if they don't show up in the top 10% of - // usages (which the view metadata provides) - sPreferred.add(ATTR_TEXT); - sPreferred.add(ATTR_CONTENT_DESCRIPTION); - sPreferred.add(ATTR_HINT); - sPreferred.add("indeterminate"); - sPreferred.add("progress"); - sPreferred.add("rating"); - sPreferred.add("max"); - assert sPreferred.size() == PREFERRED_MAP_SIZE : sPreferred.size(); - } - - /* - private static final int CATEGORY_MAP_SIZE = 62; - private static final Map<String, String> sCategories = - new HashMap<String, String>(CATEGORY_MAP_SIZE); - static { - sCategories.put("requiresFadingEdge", "Scrolling"); - sCategories.put("fadingEdgeLength", "Scrolling"); - sCategories.put("scrollbarSize", "Scrolling"); - sCategories.put("scrollbarThumbVertical", "Scrolling"); - sCategories.put("scrollbarThumbHorizontal", "Scrolling"); - sCategories.put("scrollbarTrackHorizontal", "Scrolling"); - sCategories.put("scrollbarTrackVertical", "Scrolling"); - sCategories.put("scrollbarAlwaysDrawHorizontalTrack", "Scrolling"); - sCategories.put("scrollbarAlwaysDrawVerticalTrack", "Scrolling"); - sCategories.put("scrollViewStyle", "Scrolling"); - sCategories.put("scrollbars", "Scrolling"); - sCategories.put("scrollingCache", "Scrolling"); - sCategories.put("scrollHorizontally", "Scrolling"); - sCategories.put("scrollbarFadeDuration", "Scrolling"); - sCategories.put("scrollbarDefaultDelayBeforeFade", "Scrolling"); - sCategories.put("fastScrollEnabled", "Scrolling"); - sCategories.put("smoothScrollbar", "Scrolling"); - sCategories.put("isScrollContainer", "Scrolling"); - sCategories.put("fadeScrollbars", "Scrolling"); - sCategories.put("overScrollMode", "Scrolling"); - sCategories.put("overScrollHeader", "Scrolling"); - sCategories.put("overScrollFooter", "Scrolling"); - sCategories.put("verticalScrollbarPosition", "Scrolling"); - sCategories.put("fastScrollAlwaysVisible", "Scrolling"); - sCategories.put("fastScrollThumbDrawable", "Scrolling"); - sCategories.put("fastScrollPreviewBackgroundLeft", "Scrolling"); - sCategories.put("fastScrollPreviewBackgroundRight", "Scrolling"); - sCategories.put("fastScrollTrackDrawable", "Scrolling"); - sCategories.put("fastScrollOverlayPosition", "Scrolling"); - sCategories.put("horizontalScrollViewStyle", "Scrolling"); - sCategories.put("fastScrollTextColor", "Scrolling"); - sCategories.put("scrollbarSize", "Scrolling"); - sCategories.put("scrollbarSize", "Scrolling"); - sCategories.put("scrollbarSize", "Scrolling"); - sCategories.put("scrollbarSize", "Scrolling"); - sCategories.put("scrollbarSize", "Scrolling"); - - // TODO: All the styles: radioButtonStyle, ratingBarStyle, progressBarStyle, ... - - sCategories.put("focusable", "Focus"); - sCategories.put("focusableInTouchMode", "Focus"); - sCategories.put("nextFocusLeft", "Focus"); - sCategories.put("nextFocusRight", "Focus"); - sCategories.put("nextFocusUp", "Focus"); - sCategories.put("nextFocusDown", "Focus"); - sCategories.put("descendantFocusability", "Focus"); - sCategories.put("selectAllOnFocus", "Focus"); - sCategories.put("nextFocusForward", "Focus"); - sCategories.put("colorFocusedHighlight", "Focus"); - - sCategories.put("rotation", "Transforms"); - sCategories.put("scrollX", "Transforms"); - sCategories.put("scrollY", "Transforms"); - sCategories.put("rotationX", "Transforms"); - sCategories.put("rotationY", "Transforms"); - sCategories.put("transformPivotX", "Transforms"); - sCategories.put("transformPivotY", "Transforms"); - sCategories.put("translationX", "Transforms"); - sCategories.put("translationY", "Transforms"); - sCategories.put("scaleX", "Transforms"); - sCategories.put("scaleY", "Transforms"); - - sCategories.put("width", "Size"); - sCategories.put("height", "Size"); - sCategories.put("minWidth", "Size"); - sCategories.put("minHeight", "Size"); - - sCategories.put("longClickable", "Clicks"); - sCategories.put("onClick", "Clicks"); - sCategories.put("clickable", "Clicks"); - sCategories.put("hapticFeedbackEnabled", "Clicks"); - - sCategories.put("duplicateParentState", "State"); - sCategories.put("addStatesFromChildren", "State"); - - assert sCategories.size() == CATEGORY_MAP_SIZE : sCategories.size(); - } - */ - -// private static final int PRIO_CLZ_LAYOUT = 1000; -// private static final int PRIO_CLZ_TEXT = 2000; -// private static final int PRIO_CLZ_DRAWABLE = 3000; -// private static final int PRIO_CLZ_ANIMATION = 4000; -// private static final int PRIO_CLZ_FOCUS = 5000; -// -// private static final int PRIORITY_MAP_SIZE = 100; -// private static final Map<String, Integer> sPriorities = -// new HashMap<String, Integer>(PRIORITY_MAP_SIZE); -// static { -// // TODO: I should put all the properties roughly based on their original order: this -// // will correspond to the rough order they came in with -// // TODO: How can I make similar complex properties show up adjacent; e.g. min and max -// sPriorities.put("min", PRIO_CLZ_LAYOUT); -// sPriorities.put("max", PRIO_CLZ_LAYOUT); -// -// assert sPriorities.size() == PRIORITY_MAP_SIZE : sPriorities.size(); -// } - - // TODO: Emit metadata into a file -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/PropertySheetPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/PropertySheetPage.java deleted file mode 100644 index 58fddc0ee..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/PropertySheetPage.java +++ /dev/null @@ -1,403 +0,0 @@ -/* - * 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 com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.editors.IconFactory; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart; -import com.android.ide.eclipse.adt.internal.editors.layout.properties.PropertyFactory.SortingMode; -import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode; -import com.android.ide.eclipse.adt.internal.editors.uimodel.IUiUpdateListener; -import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode; - -import org.eclipse.jface.action.Action; -import org.eclipse.jface.action.IAction; -import org.eclipse.jface.action.IMenuListener; -import org.eclipse.jface.action.IMenuManager; -import org.eclipse.jface.action.IStatusLineManager; -import org.eclipse.jface.action.IToolBarManager; -import org.eclipse.jface.action.MenuManager; -import org.eclipse.jface.action.Separator; -import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TreeSelection; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.MenuItem; -import org.eclipse.ui.ISharedImages; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.part.Page; -import org.eclipse.ui.views.properties.IPropertySheetPage; -import org.eclipse.wb.internal.core.editor.structure.IPage; -import org.eclipse.wb.internal.core.model.property.Property; -import org.eclipse.wb.internal.core.model.property.table.IPropertyExceptionHandler; -import org.eclipse.wb.internal.core.model.property.table.PropertyTable; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -/** - * Property sheet page used when the graphical layout editor is chosen - */ -public class PropertySheetPage extends Page - implements IPropertySheetPage, IUiUpdateListener, IPage { - private PropertyTable mPropertyTable; - private final GraphicalEditorPart mEditor; - private Property mActiveProperty; - private Action mDefaultValueAction; - private Action mShowAdvancedPropertiesAction; - private Action mSortAlphaAction; - private Action mCollapseAll; - private Action mExpandAll; - private List<CanvasViewInfo> mSelection; - - private static final String EXPAND_DISABLED_ICON = "expandall-disabled"; //$NON-NLS-1$ - private static final String EXPAND_ICON = "expandall"; //$NON-NLS-1$ - private static final String DEFAULT_ICON = "properties_default"; //$NON-NLS-1$ - private static final String ADVANCED_ICON = "filter_advanced_properties"; //$NON-NLS-1$ - private static final String ALPHA_ICON = "sort_alpha"; //$NON-NLS-1$ - // TODO: goto-definition.png - - /** - * Constructs a new {@link PropertySheetPage} associated with the given - * editor - * - * @param editor the editor associated with this property sheet page - */ - public PropertySheetPage(GraphicalEditorPart editor) { - mEditor = editor; - } - - private PropertyFactory getPropertyFactory() { - return mEditor.getPropertyFactory(); - } - - @Override - public void createControl(Composite parent) { - assert parent != null; - mPropertyTable = new PropertyTable(parent, SWT.NONE); - mPropertyTable.setExceptionHandler(new IPropertyExceptionHandler() { - @Override - public void handle(Throwable e) { - AdtPlugin.log(e, null); - } - }); - mPropertyTable.setDefaultCollapsedNames(Arrays.asList( - "Deprecated", - "Layout Parameters", - "Layout Parameters|Margins")); - - createActions(); - setPropertyTableContextMenu(); - } - - @Override - public void selectionChanged(IWorkbenchPart part, ISelection selection) { - if (selection instanceof TreeSelection - && mPropertyTable != null && !mPropertyTable.isDisposed()) { - TreeSelection treeSelection = (TreeSelection) selection; - - // We get a lot of repeated selection requests for the same selection - // as before, so try to eliminate these - if (mSelection != null) { - if (mSelection.isEmpty()) { - if (treeSelection.isEmpty()) { - return; - } - } else { - int selectionCount = treeSelection.size(); - if (selectionCount == mSelection.size()) { - boolean same = true; - Iterator<?> iterator = treeSelection.iterator(); - for (int i = 0, n = selectionCount; i < n && iterator.hasNext(); i++) { - Object next = iterator.next(); - if (next instanceof CanvasViewInfo) { - CanvasViewInfo info = (CanvasViewInfo) next; - if (info != mSelection.get(i)) { - same = false; - break; - } - } else { - same = false; - break; - } - } - if (same) { - return; - } - } - } - } - - stopTrackingSelection(); - - if (treeSelection.isEmpty()) { - mSelection = Collections.emptyList(); - } else { - int selectionCount = treeSelection.size(); - List<CanvasViewInfo> newSelection = new ArrayList<CanvasViewInfo>(selectionCount); - Iterator<?> iterator = treeSelection.iterator(); - while (iterator.hasNext()) { - Object next = iterator.next(); - if (next instanceof CanvasViewInfo) { - CanvasViewInfo info = (CanvasViewInfo) next; - newSelection.add(info); - } - } - mSelection = newSelection; - } - - startTrackingSelection(); - - refreshProperties(); - } - } - - @Override - public void dispose() { - stopTrackingSelection(); - super.dispose(); - } - - private void startTrackingSelection() { - if (mSelection != null && !mSelection.isEmpty()) { - for (CanvasViewInfo item : mSelection) { - UiViewElementNode node = item.getUiViewNode(); - if (node != null) { - node.addUpdateListener(this); - } - } - } - } - - private void stopTrackingSelection() { - if (mSelection != null && !mSelection.isEmpty()) { - for (CanvasViewInfo item : mSelection) { - UiViewElementNode node = item.getUiViewNode(); - if (node != null) { - node.removeUpdateListener(this); - } - } - } - mSelection = null; - } - - // Implements IUiUpdateListener - @Override - public void uiElementNodeUpdated(UiElementNode node, UiUpdateState state) { - refreshProperties(); - } - - @Override - public Control getControl() { - return mPropertyTable; - } - - @Override - public void setFocus() { - mPropertyTable.setFocus(); - } - - @Override - public void makeContributions(IMenuManager menuManager, - IToolBarManager toolBarManager, IStatusLineManager statusLineManager) { - toolBarManager.add(mShowAdvancedPropertiesAction); - toolBarManager.add(new Separator()); - toolBarManager.add(mSortAlphaAction); - toolBarManager.add(new Separator()); - toolBarManager.add(mDefaultValueAction); - toolBarManager.add(new Separator()); - toolBarManager.add(mExpandAll); - toolBarManager.add(mCollapseAll); - toolBarManager.add(new Separator()); - } - - private void createActions() { - ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); - IconFactory iconFactory = IconFactory.getInstance(); - - mExpandAll = new PropertySheetAction( - IAction.AS_PUSH_BUTTON, - "Expand All", - ACTION_EXPAND, - iconFactory.getImageDescriptor(EXPAND_ICON), - iconFactory.getImageDescriptor(EXPAND_DISABLED_ICON)); - - mCollapseAll = new PropertySheetAction( - IAction.AS_PUSH_BUTTON, - "Collapse All", - ACTION_COLLAPSE, - sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_COLLAPSEALL), - sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_COLLAPSEALL_DISABLED)); - - mShowAdvancedPropertiesAction = new PropertySheetAction( - IAction.AS_CHECK_BOX, - "Show Advanced Properties", - ACTION_SHOW_ADVANCED, - iconFactory.getImageDescriptor(ADVANCED_ICON), - null); - - mSortAlphaAction = new PropertySheetAction( - IAction.AS_CHECK_BOX, - "Sort Alphabetically", - ACTION_SORT_ALPHA, - iconFactory.getImageDescriptor(ALPHA_ICON), - null); - - mDefaultValueAction = new PropertySheetAction( - IAction.AS_PUSH_BUTTON, - "Restore Default Value", - ACTION_DEFAULT_VALUE, - iconFactory.getImageDescriptor(DEFAULT_ICON), - null); - - // Listen on the selection in the property sheet so we can update the - // Restore Default Value action - ISelectionChangedListener listener = new ISelectionChangedListener() { - @Override - public void selectionChanged(SelectionChangedEvent event) { - StructuredSelection selection = (StructuredSelection) event.getSelection(); - mActiveProperty = (Property) selection.getFirstElement(); - updateDefaultValueAction(); - } - }; - mPropertyTable.addSelectionChangedListener(listener); - } - - /** - * Updates the state of {@link #mDefaultValueAction}. - */ - private void updateDefaultValueAction() { - if (mActiveProperty != null) { - try { - mDefaultValueAction.setEnabled(mActiveProperty.isModified()); - } catch (Exception e) { - AdtPlugin.log(e, null); - } - } else { - mDefaultValueAction.setEnabled(false); - } - } - - /** - * Sets the context menu for {@link #mPropertyTable}. - */ - private void setPropertyTableContextMenu() { - final MenuManager manager = new MenuManager(); - manager.setRemoveAllWhenShown(true); - manager.addMenuListener(new IMenuListener() { - @Override - public void menuAboutToShow(IMenuManager m) { - // dispose items to avoid caching - for (MenuItem item : manager.getMenu().getItems()) { - item.dispose(); - } - // apply new items - fillContextMenu(); - } - - private void fillContextMenu() { - manager.add(mDefaultValueAction); - manager.add(mSortAlphaAction); - manager.add(mShowAdvancedPropertiesAction); - } - }); - - mPropertyTable.setMenu(manager.createContextMenu(mPropertyTable)); - } - - /** - * Shows {@link Property}'s of current objects. - */ - private void refreshProperties() { - PropertyFactory factory = getPropertyFactory(); - mPropertyTable.setInput(factory.getProperties(mSelection)); - updateDefaultValueAction(); - } - - // ---- Actions ---- - - private static final int ACTION_DEFAULT_VALUE = 1; - private static final int ACTION_SHOW_ADVANCED = 2; - private static final int ACTION_COLLAPSE = 3; - private static final int ACTION_EXPAND = 4; - private static final int ACTION_SORT_ALPHA = 5; - - private class PropertySheetAction extends Action { - private final int mAction; - - private PropertySheetAction(int style, String label, int action, - ImageDescriptor imageDesc, ImageDescriptor disabledImageDesc) { - super(label, style); - mAction = action; - setImageDescriptor(imageDesc); - if (disabledImageDesc != null) { - setDisabledImageDescriptor(disabledImageDesc); - } - setToolTipText(label); - } - - @Override - public void run() { - switch (mAction) { - case ACTION_COLLAPSE: { - mPropertyTable.collapseAll(); - break; - } - case ACTION_EXPAND: { - mPropertyTable.expandAll(); - break; - } - case ACTION_SHOW_ADVANCED: { - boolean show = mShowAdvancedPropertiesAction.isChecked(); - mPropertyTable.setShowAdvancedProperties(show); - break; - } - case ACTION_SORT_ALPHA: { - boolean isAlphabetical = mSortAlphaAction.isChecked(); - getPropertyFactory().setSortingMode( - isAlphabetical ? SortingMode.ALPHABETICAL : PropertyFactory.DEFAULT_MODE); - refreshProperties(); - break; - } - case ACTION_DEFAULT_VALUE: - try { - mActiveProperty.setValue(Property.UNKNOWN_VALUE); - } catch (Exception e) { - // Ignore warnings from setters - } - break; - default: - assert false : mAction; - } - } - } - - @Override - public void setToolBar(IToolBarManager toolBarManager) { - makeContributions(null, toolBarManager, null); - toolBarManager.update(false); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/PropertyValueCompleter.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/PropertyValueCompleter.java deleted file mode 100644 index f2bf07312..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/PropertyValueCompleter.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor; -import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor; - -class PropertyValueCompleter extends ValueCompleter { - private final XmlProperty mProperty; - - PropertyValueCompleter(XmlProperty property) { - mProperty = property; - } - - @Override - @Nullable - protected CommonXmlEditor getEditor() { - return mProperty.getXmlEditor(); - } - - @Override - @NonNull - protected AttributeDescriptor getDescriptor() { - return mProperty.getDescriptor(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/ResourceValueCompleter.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/ResourceValueCompleter.java deleted file mode 100644 index 081ec8069..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/ResourceValueCompleter.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * 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.ANDROID_PKG; -import static com.android.SdkConstants.ANDROID_PREFIX; -import static com.android.SdkConstants.ANDROID_THEME_PREFIX; -import static com.android.SdkConstants.NEW_ID_PREFIX; -import static com.android.SdkConstants.PREFIX_RESOURCE_REF; -import static com.android.SdkConstants.PREFIX_THEME_REF; - -import com.android.ide.common.resources.ResourceItem; -import com.android.ide.common.resources.ResourceRepository; -import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; -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.uimodel.UiResourceAttributeNode; -import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; -import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; -import com.android.resources.ResourceType; -import com.android.utils.SdkUtils; - -import org.eclipse.core.resources.IProject; -import org.eclipse.jface.fieldassist.ContentProposal; -import org.eclipse.jface.fieldassist.IContentProposal; -import org.eclipse.jface.fieldassist.IContentProposalProvider; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Resource value completion for the given property - * <p> - * TODO: - * <ul> - * <li>also offer other values seen in the app - * <li>also offer previously set values for this property - * <li>also complete on properties - * </ul> - */ -class ResourceValueCompleter implements IContentProposalProvider { - protected final XmlProperty xmlProperty; - - ResourceValueCompleter(XmlProperty xmlProperty) { - this.xmlProperty = xmlProperty; - } - - @Override - public IContentProposal[] getProposals(String contents, int position) { - if (contents.startsWith(PREFIX_RESOURCE_REF)) { - CommonXmlEditor editor = this.xmlProperty.getXmlEditor(); - if (editor != null) { - String[] matches = computeResourceStringMatches( - editor, - this.xmlProperty.mDescriptor, contents.substring(0, position)); - List<IContentProposal> proposals = null; - if (matches != null && matches.length > 0) { - proposals = new ArrayList<IContentProposal>(matches.length); - for (String match : matches) { - proposals.add(new ContentProposal(match)); - } - return proposals.toArray(new IContentProposal[proposals.size()]); - } - } - } - - return new IContentProposal[0]; - } - - /** - * Similar to {@link UiResourceAttributeNode#computeResourceStringMatches} - * but computes complete results up front rather than dividing it up into - * smaller chunks like @{code @android:}, {@code string/}, and {@code ok}. - */ - static String[] computeResourceStringMatches(AndroidXmlEditor editor, - AttributeDescriptor attributeDescriptor, String prefix) { - List<String> results = new ArrayList<String>(200); - - // System matches: only do this if the value already matches at least @a, - // and doesn't start with something that can't possibly be @android - if (prefix.startsWith("@a") && //$NON-NLS-1$ - prefix.regionMatches(true /* ignoreCase */, 0, ANDROID_PREFIX, 0, - Math.min(prefix.length() - 1, ANDROID_PREFIX.length()))) { - AndroidTargetData data = editor.getTargetData(); - if (data != null) { - ResourceRepository repository = data.getFrameworkResources(); - addMatches(repository, prefix, true /* isSystem */, results); - } - } else if (prefix.startsWith("?") && //$NON-NLS-1$ - prefix.regionMatches(true /* ignoreCase */, 0, ANDROID_THEME_PREFIX, 0, - Math.min(prefix.length() - 1, ANDROID_THEME_PREFIX.length()))) { - AndroidTargetData data = editor.getTargetData(); - if (data != null) { - ResourceRepository repository = data.getFrameworkResources(); - addMatches(repository, prefix, true /* isSystem */, results); - } - } - - - // When completing project resources skip framework resources unless - // the prefix possibly completes both, such as "@an" which can match - // both the project resource @animator as well as @android:string - if (!prefix.startsWith("@and") && !prefix.startsWith("?and")) { //$NON-NLS-1$ //$NON-NLS-2$ - IProject project = editor.getProject(); - if (project != null) { - // get the resource repository for this project and the system resources. - ResourceManager manager = ResourceManager.getInstance(); - ResourceRepository repository = manager.getProjectResources(project); - if (repository != null) { - // We have a style name and a repository. Find all resources that match this - // type and recreate suggestions out of them. - addMatches(repository, prefix, false /* isSystem */, results); - } - - } - } - - if (attributeDescriptor != null) { - UiResourceAttributeNode.sortAttributeChoices(attributeDescriptor, results); - } else { - Collections.sort(results); - } - - return results.toArray(new String[results.size()]); - } - - private static void addMatches(ResourceRepository repository, String prefix, boolean isSystem, - List<String> results) { - int typeStart = isSystem - ? ANDROID_PREFIX.length() : PREFIX_RESOURCE_REF.length(); - - for (ResourceType type : repository.getAvailableResourceTypes()) { - if (prefix.regionMatches(typeStart, type.getName(), 0, - Math.min(type.getName().length(), prefix.length() - typeStart))) { - StringBuilder sb = new StringBuilder(); - if (prefix.length() == 0 || prefix.startsWith(PREFIX_RESOURCE_REF)) { - sb.append(PREFIX_RESOURCE_REF); - } else { - if (type != ResourceType.ATTR) { - continue; - } - sb.append(PREFIX_THEME_REF); - } - - if (type == ResourceType.ID && prefix.startsWith(NEW_ID_PREFIX)) { - sb.append('+'); - } - - if (isSystem) { - sb.append(ANDROID_PKG).append(':'); - } - - sb.append(type.getName()).append('/'); - String base = sb.toString(); - - int nameStart = typeStart + type.getName().length() + 1; // +1: add "/" divider - String namePrefix = - prefix.length() <= nameStart ? "" : prefix.substring(nameStart); - for (ResourceItem item : repository.getResourceItemsOfType(type)) { - String name = item.getName(); - if (SdkUtils.startsWithIgnoreCase(name, namePrefix)) { - results.add(base + name); - } - } - } - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/StringXmlPropertyDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/StringXmlPropertyDialog.java deleted file mode 100644 index fb7e45902..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/StringXmlPropertyDialog.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.wb.internal.core.model.property.Property; -import org.eclipse.wb.internal.core.model.property.editor.string.StringPropertyDialog; - -class StringXmlPropertyDialog extends StringPropertyDialog { - StringXmlPropertyDialog(Shell parentShell, Property property) throws Exception { - super(parentShell, property); - } - - @Override - protected boolean isMultiLine() { - return false; - } - - @Override - protected Control createDialogArea(Composite parent) { - Composite area = (Composite) super.createDialogArea(parent); - - Composite workaround = PropertyFactory.addWorkaround(area); - if (workaround != null) { - workaround.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1)); - } - - return area; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/ValueCompleter.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/ValueCompleter.java deleted file mode 100644 index 5559349fc..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/ValueCompleter.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * 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_TEXT_SIZE; -import static com.android.SdkConstants.PREFIX_RESOURCE_REF; -import static com.android.SdkConstants.PREFIX_THEME_REF; -import static com.android.SdkConstants.UNIT_DP; -import static com.android.SdkConstants.UNIT_SP; -import static com.android.SdkConstants.VALUE_FALSE; -import static com.android.SdkConstants.VALUE_TRUE; -import static com.android.ide.common.api.IAttributeInfo.Format.BOOLEAN; -import static com.android.ide.common.api.IAttributeInfo.Format.DIMENSION; -import static com.android.ide.common.api.IAttributeInfo.Format.ENUM; -import static com.android.ide.common.api.IAttributeInfo.Format.FLAG; -import static com.android.ide.common.api.IAttributeInfo.Format.FLOAT; -import static com.android.ide.common.api.IAttributeInfo.Format.INTEGER; -import static com.android.ide.common.api.IAttributeInfo.Format.REFERENCE; -import static com.android.ide.common.api.IAttributeInfo.Format.STRING; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.common.api.IAttributeInfo; -import com.android.ide.common.api.IAttributeInfo.Format; -import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor; -import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor; -import com.android.utils.SdkUtils; - -import org.eclipse.jface.fieldassist.ContentProposal; -import org.eclipse.jface.fieldassist.IContentProposal; -import org.eclipse.jface.fieldassist.IContentProposalProvider; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; - -/** - * An {@link IContentProposalProvider} which completes possible property values - * for Android properties, completing resource strings, flag values, enum - * values, as well as dimension units. - */ -abstract class ValueCompleter implements IContentProposalProvider { - @Nullable - protected abstract CommonXmlEditor getEditor(); - - @NonNull - protected abstract AttributeDescriptor getDescriptor(); - - @Override - public IContentProposal[] getProposals(String contents, int position) { - AttributeDescriptor descriptor = getDescriptor(); - IAttributeInfo info = descriptor.getAttributeInfo(); - EnumSet<Format> formats = info.getFormats(); - - List<IContentProposal> proposals = new ArrayList<IContentProposal>(); - - String prefix = contents; // TODO: Go back to position inside the array? - - // TODO: If the user is typing in a number, or a number plus a prefix of a dimension unit, - // then propose that number plus the completed dimension unit (using sp for text, dp - // for other properties and maybe both if I'm not sure) - if (formats.contains(STRING) - && !contents.isEmpty() - && (formats.size() > 1 && formats.contains(REFERENCE) || - formats.size() > 2) - && !contents.startsWith(PREFIX_RESOURCE_REF) - && !contents.startsWith(PREFIX_THEME_REF)) { - proposals.add(new ContentProposal(contents)); - } - - if (!contents.isEmpty() && Character.isDigit(contents.charAt(0)) - && (formats.contains(DIMENSION) - || formats.contains(INTEGER) - || formats.contains(FLOAT))) { - StringBuilder sb = new StringBuilder(); - for (int i = 0, n = contents.length(); i < n; i++) { - char c = contents.charAt(i); - if (Character.isDigit(c)) { - sb.append(c); - } else { - break; - } - } - - String number = sb.toString(); - if (formats.contains(Format.DIMENSION)) { - if (descriptor.getXmlLocalName().equals(ATTR_TEXT_SIZE)) { - proposals.add(new ContentProposal(number + UNIT_SP)); - } - proposals.add(new ContentProposal(number + UNIT_DP)); - } else if (formats.contains(Format.INTEGER)) { - proposals.add(new ContentProposal(number)); - } - // Perhaps offer other units too -- see AndroidContentAssist.sDimensionUnits - } - - if (formats.contains(REFERENCE) || contents.startsWith(PREFIX_RESOURCE_REF) - || contents.startsWith(PREFIX_THEME_REF)) { - CommonXmlEditor editor = getEditor(); - if (editor != null) { - String[] matches = ResourceValueCompleter.computeResourceStringMatches( - editor, - descriptor, contents.substring(0, position)); - for (String match : matches) { - proposals.add(new ContentProposal(match)); - } - } - } - - if (formats.contains(FLAG)) { - String[] values = info.getFlagValues(); - if (values != null) { - // Flag completion - int flagStart = prefix.lastIndexOf('|'); - String prepend = null; - if (flagStart != -1) { - prepend = prefix.substring(0, flagStart + 1); - prefix = prefix.substring(flagStart + 1).trim(); - } - - boolean exactMatch = false; - for (String value : values) { - if (prefix.equals(value)) { - exactMatch = true; - proposals.add(new ContentProposal(contents)); - - break; - } - } - - if (exactMatch) { - prepend = contents + '|'; - prefix = ""; - } - - for (String value : values) { - if (SdkUtils.startsWithIgnoreCase(value, prefix)) { - if (prepend != null && prepend.contains(value)) { - continue; - } - String match; - if (prepend != null) { - match = prepend + value; - } else { - match = value; - } - proposals.add(new ContentProposal(match)); - } - } - } - } else if (formats.contains(ENUM)) { - String[] values = info.getEnumValues(); - if (values != null) { - for (String value : values) { - if (SdkUtils.startsWithIgnoreCase(value, prefix)) { - proposals.add(new ContentProposal(value)); - } - } - - for (String value : values) { - if (!SdkUtils.startsWithIgnoreCase(value, prefix)) { - proposals.add(new ContentProposal(value)); - } - } - } - } else if (formats.contains(BOOLEAN)) { - proposals.add(new ContentProposal(VALUE_TRUE)); - proposals.add(new ContentProposal(VALUE_FALSE)); - } - - return proposals.toArray(new IContentProposal[proposals.size()]); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/XmlProperty.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/XmlProperty.java deleted file mode 100644 index a320b682d..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/XmlProperty.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * 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(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/XmlPropertyComposite.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/XmlPropertyComposite.java deleted file mode 100644 index af9e13b3e..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/XmlPropertyComposite.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 com.android.annotations.NonNull; -import com.google.common.base.Objects; - -import org.eclipse.wb.internal.core.model.property.Property; - -import java.util.Arrays; - -/** - * Property holding multiple instances of the same {@link XmlProperty} (but - * bound to difference objects. This is used when multiple objects are selected - * in the layout editor and the common properties are shown; editing a value - * will (via {@link #setValue(Object)}) set it on all selected objects. - * <p> - * Similar to - * org.eclipse.wb.internal.core.model.property.GenericPropertyComposite - */ -class XmlPropertyComposite extends XmlProperty { - private static final Object NO_VALUE = new Object(); - - private final XmlProperty[] mProperties; - - public XmlPropertyComposite(XmlProperty primary, XmlProperty[] properties) { - super( - primary.getEditor(), - primary.getFactory(), - primary.getNode(), - primary.getDescriptor()); - mProperties = properties; - } - - @Override - @NonNull - public String getTitle() { - return mProperties[0].getTitle(); - } - - @Override - public int hashCode() { - return mProperties.length; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - - if (obj instanceof XmlPropertyComposite) { - XmlPropertyComposite property = (XmlPropertyComposite) obj; - return Arrays.equals(mProperties, property.mProperties); - } - - return false; - } - - @Override - public boolean isModified() throws Exception { - for (Property property : mProperties) { - if (property.isModified()) { - return true; - } - } - - return false; - } - - @Override - public Object getValue() throws Exception { - Object value = NO_VALUE; - for (Property property : mProperties) { - Object propertyValue = property.getValue(); - if (value == NO_VALUE) { - value = propertyValue; - } else if (!Objects.equal(value, propertyValue)) { - return UNKNOWN_VALUE; - } - } - - return value; - } - - @Override - public void setValue(final Object value) throws Exception { - // TBD: Wrap in ExecutionUtils.run? - for (Property property : mProperties) { - property.setValue(value); - } - } - - @NonNull - public static XmlPropertyComposite create(Property... properties) { - // Cast from Property into XmlProperty - XmlProperty[] xmlProperties = new XmlProperty[properties.length]; - for (int i = 0; i < properties.length; i++) { - Property property = properties[i]; - xmlProperties[i] = (XmlProperty) property; - } - - XmlPropertyComposite composite = new XmlPropertyComposite(xmlProperties[0], xmlProperties); - composite.setCategory(xmlProperties[0].getCategory()); - return composite; - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/XmlPropertyEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/XmlPropertyEditor.java deleted file mode 100644 index 87fb0e6ed..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/properties/XmlPropertyEditor.java +++ /dev/null @@ -1,548 +0,0 @@ -/* - * 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.ANDROID_PREFIX; -import static com.android.SdkConstants.ANDROID_THEME_PREFIX; -import static com.android.SdkConstants.ATTR_ID; -import static com.android.SdkConstants.DOT_PNG; -import static com.android.SdkConstants.DOT_XML; -import static com.android.SdkConstants.NEW_ID_PREFIX; -import static com.android.SdkConstants.PREFIX_RESOURCE_REF; -import static com.android.SdkConstants.PREFIX_THEME_REF; -import static com.android.ide.common.layout.BaseViewRule.stripIdPrefix; - -import com.android.annotations.NonNull; -import com.android.ide.common.api.IAttributeInfo; -import com.android.ide.common.api.IAttributeInfo.Format; -import com.android.ide.common.layout.BaseViewRule; -import com.android.ide.common.rendering.api.ResourceValue; -import com.android.ide.common.resources.ResourceRepository; -import com.android.ide.common.resources.ResourceResolver; -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.layout.LayoutEditorDelegate; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageUtils; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.LayoutCanvas; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderService; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SelectionManager; -import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SwtUtils; -import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy; -import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; -import com.android.ide.eclipse.adt.internal.refactorings.core.RenameResourceWizard; -import com.android.ide.eclipse.adt.internal.refactorings.core.RenameResult; -import com.android.ide.eclipse.adt.internal.resources.ResourceHelper; -import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; -import com.android.ide.eclipse.adt.internal.ui.ReferenceChooserDialog; -import com.android.ide.eclipse.adt.internal.ui.ResourceChooser; -import com.android.ide.eclipse.adt.internal.ui.ResourcePreviewHelper; -import com.android.resources.ResourceType; -import com.google.common.collect.Maps; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.QualifiedName; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.dialogs.MessageDialogWithToggle; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.graphics.ImageData; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.wb.draw2d.IColorConstants; -import org.eclipse.wb.internal.core.model.property.Property; -import org.eclipse.wb.internal.core.model.property.editor.AbstractTextPropertyEditor; -import org.eclipse.wb.internal.core.model.property.editor.presentation.ButtonPropertyEditorPresentation; -import org.eclipse.wb.internal.core.model.property.editor.presentation.PropertyEditorPresentation; -import org.eclipse.wb.internal.core.model.property.table.PropertyTable; -import org.eclipse.wb.internal.core.utils.ui.DrawUtils; - -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import java.util.Map; - -import javax.imageio.ImageIO; - -/** - * Special property editor used for the {@link XmlProperty} instances which handles - * editing the XML properties, rendering defaults by looking up the actual colors and images, - */ -class XmlPropertyEditor extends AbstractTextPropertyEditor { - public static final XmlPropertyEditor INSTANCE = new XmlPropertyEditor(); - private static final int SAMPLE_SIZE = 10; - private static final int SAMPLE_MARGIN = 3; - - protected XmlPropertyEditor() { - } - - private final PropertyEditorPresentation mPresentation = - new ButtonPropertyEditorPresentation() { - @Override - protected void onClick(PropertyTable propertyTable, Property property) throws Exception { - openDialog(propertyTable, property); - } - }; - - @Override - public PropertyEditorPresentation getPresentation() { - return mPresentation; - } - - @Override - public String getText(Property property) throws Exception { - Object value = property.getValue(); - if (value instanceof String) { - return (String) value; - } - return null; - } - - @Override - protected String getEditorText(Property property) throws Exception { - return getText(property); - } - - @Override - public void paint(Property property, GC gc, int x, int y, int width, int height) - throws Exception { - String text = getText(property); - if (text != null) { - ResourceValue resValue = null; - String resolvedText = null; - - // TODO: Use the constants for @, ?, @android: etc - if (text.startsWith("@") || text.startsWith("?")) { //$NON-NLS-1$ //$NON-NLS-2$ - // Yes, try to resolve it in order to show better info - XmlProperty xmlProperty = (XmlProperty) property; - GraphicalEditorPart graphicalEditor = xmlProperty.getGraphicalEditor(); - if (graphicalEditor != null) { - ResourceResolver resolver = graphicalEditor.getResourceResolver(); - boolean isFramework = text.startsWith(ANDROID_PREFIX) - || text.startsWith(ANDROID_THEME_PREFIX); - resValue = resolver.findResValue(text, isFramework); - while (resValue != null && resValue.getValue() != null) { - String value = resValue.getValue(); - if (value.startsWith(PREFIX_RESOURCE_REF) - || value.startsWith(PREFIX_THEME_REF)) { - // TODO: do I have to strip off the @ too? - isFramework = isFramework - || value.startsWith(ANDROID_PREFIX) - || value.startsWith(ANDROID_THEME_PREFIX); - ResourceValue v = resolver.findResValue(text, isFramework); - if (v != null && !value.equals(v.getValue())) { - resValue = v; - } else { - break; - } - } else { - break; - } - } - } - } else if (text.startsWith("#") && text.matches("#\\p{XDigit}+")) { //$NON-NLS-1$ - resValue = new ResourceValue(ResourceType.COLOR, property.getName(), text, false); - } - - if (resValue != null && resValue.getValue() != null) { - String value = resValue.getValue(); - // Decide whether it's a color, an image, a nine patch etc - // and decide how to render it - if (value.startsWith("#") || value.endsWith(DOT_XML) //$NON-NLS-1$ - && value.contains("res/color")) { //$NON-NLS-1$ // TBD: File.separator? - XmlProperty xmlProperty = (XmlProperty) property; - GraphicalEditorPart graphicalEditor = xmlProperty.getGraphicalEditor(); - if (graphicalEditor != null) { - ResourceResolver resolver = graphicalEditor.getResourceResolver(); - RGB rgb = ResourceHelper.resolveColor(resolver, resValue); - if (rgb != null) { - Color color = new Color(gc.getDevice(), rgb); - // draw color sample - Color oldBackground = gc.getBackground(); - Color oldForeground = gc.getForeground(); - try { - int width_c = SAMPLE_SIZE; - int height_c = SAMPLE_SIZE; - int x_c = x; - int y_c = y + (height - height_c) / 2; - // update rest bounds - int delta = SAMPLE_SIZE + SAMPLE_MARGIN; - x += delta; - width -= delta; - // fill - gc.setBackground(color); - gc.fillRectangle(x_c, y_c, width_c, height_c); - // draw line - gc.setForeground(IColorConstants.gray); - gc.drawRectangle(x_c, y_c, width_c, height_c); - } finally { - gc.setBackground(oldBackground); - gc.setForeground(oldForeground); - } - color.dispose(); - } - } - } else { - Image swtImage = null; - if (value.endsWith(DOT_XML) && value.contains("res/drawable")) { // TBD: Filesep? - Map<String, Image> cache = getImageCache(property); - swtImage = cache.get(value); - if (swtImage == null) { - XmlProperty xmlProperty = (XmlProperty) property; - GraphicalEditorPart graphicalEditor = xmlProperty.getGraphicalEditor(); - RenderService service = RenderService.create(graphicalEditor); - service.setOverrideRenderSize(SAMPLE_SIZE, SAMPLE_SIZE); - BufferedImage drawable = service.renderDrawable(resValue); - if (drawable != null) { - swtImage = SwtUtils.convertToSwt(gc.getDevice(), drawable, - true /*transferAlpha*/, -1); - cache.put(value, swtImage); - } - } - } else if (value.endsWith(DOT_PNG)) { - // TODO: 9-patch handling? - //if (text.endsWith(DOT_9PNG)) { - // // 9-patch image: How do we paint this? - // URL url = new File(text).toURI().toURL(); - // NinePatch ninepatch = NinePatch.load(url, false /* ?? */); - // BufferedImage image = ninepatch.getImage(); - //} - Map<String, Image> cache = getImageCache(property); - swtImage = cache.get(value); - if (swtImage == null) { - File file = new File(value); - if (file.exists()) { - try { - BufferedImage awtImage = ImageIO.read(file); - if (awtImage != null && awtImage.getWidth() > 0 - && awtImage.getHeight() > 0) { - awtImage = ImageUtils.cropBlank(awtImage, null); - if (awtImage != null) { - // Scale image - int imageWidth = awtImage.getWidth(); - int imageHeight = awtImage.getHeight(); - int maxWidth = 3 * height; - - if (imageWidth > maxWidth || imageHeight > height) { - double scale = height / (double) imageHeight; - int scaledWidth = (int) (imageWidth * scale); - if (scaledWidth > maxWidth) { - scale = maxWidth / (double) imageWidth; - } - awtImage = ImageUtils.scale(awtImage, scale, - scale); - } - swtImage = SwtUtils.convertToSwt(gc.getDevice(), - awtImage, true /*transferAlpha*/, -1); - } - } - } catch (IOException e) { - AdtPlugin.log(e, value); - } - } - cache.put(value, swtImage); - } - - } else if (value != null) { - // It's a normal string: if different from the text, paint - // it in parentheses, e.g. - // @string/foo: Foo Bar (probably cropped) - if (!value.equals(text) && !value.equals("@null")) { //$NON-NLS-1$ - resolvedText = value; - } - } - - if (swtImage != null) { - // Make a square the size of the height - ImageData imageData = swtImage.getImageData(); - int imageWidth = imageData.width; - int imageHeight = imageData.height; - if (imageWidth > 0 && imageHeight > 0) { - gc.drawImage(swtImage, x, y + (height - imageHeight) / 2); - int delta = imageWidth + SAMPLE_MARGIN; - x += delta; - width -= delta; - } - } - } - } - - DrawUtils.drawStringCV(gc, text, x, y, width, height); - - if (resolvedText != null && resolvedText.length() > 0) { - Point size = gc.stringExtent(text); - x += size.x; - width -= size.x; - - x += SAMPLE_MARGIN; - width -= SAMPLE_MARGIN; - - if (width > 0) { - Color oldForeground = gc.getForeground(); - try { - gc.setForeground(PropertyTable.COLOR_PROPERTY_FG_DEFAULT); - DrawUtils.drawStringCV(gc, '(' + resolvedText + ')', x, y, width, height); - } finally { - gc.setForeground(oldForeground); - } - } - } - } - } - - @Override - protected boolean setEditorText(Property property, String text) throws Exception { - Object oldValue = property.getValue(); - String old = oldValue != null ? oldValue.toString() : null; - - // If users enters a new id without specifying the @id/@+id prefix, insert it - boolean isId = isIdProperty(property); - if (isId && !text.startsWith(PREFIX_RESOURCE_REF)) { - text = NEW_ID_PREFIX + text; - } - - // Handle id refactoring: if you change an id, may want to update references too. - // Ask user. - if (isId && property instanceof XmlProperty - && old != null && !old.isEmpty() - && text != null && !text.isEmpty() - && !text.equals(old)) { - XmlProperty xmlProperty = (XmlProperty) property; - IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore(); - String refactorPref = store.getString(AdtPrefs.PREFS_REFACTOR_IDS); - boolean performRefactor = false; - Shell shell = AdtPlugin.getShell(); - if (refactorPref == null - || refactorPref.isEmpty() - || refactorPref.equals(MessageDialogWithToggle.PROMPT)) { - MessageDialogWithToggle dialog = - MessageDialogWithToggle.openYesNoCancelQuestion( - shell, - "Update References?", - "Update all references as well? " + - "This will update all XML references and Java R field references.", - "Do not show again", - false, - store, - AdtPrefs.PREFS_REFACTOR_IDS); - switch (dialog.getReturnCode()) { - case IDialogConstants.CANCEL_ID: - return false; - case IDialogConstants.YES_ID: - performRefactor = true; - break; - case IDialogConstants.NO_ID: - performRefactor = false; - break; - } - } else { - performRefactor = refactorPref.equals(MessageDialogWithToggle.ALWAYS); - } - if (performRefactor) { - CommonXmlEditor xmlEditor = xmlProperty.getXmlEditor(); - if (xmlEditor != null) { - IProject project = xmlEditor.getProject(); - if (project != null && shell != null) { - RenameResourceWizard.renameResource(shell, project, - ResourceType.ID, stripIdPrefix(old), stripIdPrefix(text), false); - } - } - } - } - - property.setValue(text); - - return true; - } - - private static boolean isIdProperty(Property property) { - XmlProperty xmlProperty = (XmlProperty) property; - return xmlProperty.getDescriptor().getXmlLocalName().equals(ATTR_ID); - } - - private void openDialog(PropertyTable propertyTable, Property property) throws Exception { - XmlProperty xmlProperty = (XmlProperty) property; - IAttributeInfo attributeInfo = xmlProperty.getDescriptor().getAttributeInfo(); - - if (isIdProperty(property)) { - Object value = xmlProperty.getValue(); - if (value != null && !value.toString().isEmpty()) { - GraphicalEditorPart editor = xmlProperty.getGraphicalEditor(); - if (editor != null) { - LayoutCanvas canvas = editor.getCanvasControl(); - SelectionManager manager = canvas.getSelectionManager(); - - NodeProxy primary = canvas.getNodeFactory().create(xmlProperty.getNode()); - if (primary != null) { - RenameResult result = manager.performRename(primary, null); - if (result.isCanceled()) { - return; - } else if (!result.isUnavailable()) { - String name = result.getName(); - String id = NEW_ID_PREFIX + BaseViewRule.stripIdPrefix(name); - xmlProperty.setValue(id); - return; - } - } - } - } - - // When editing the id attribute, don't offer a resource chooser: usually - // you want to enter a *new* id here - attributeInfo = null; - } - - boolean referenceAllowed = false; - if (attributeInfo != null) { - EnumSet<Format> formats = attributeInfo.getFormats(); - ResourceType type = null; - List<ResourceType> types = null; - if (formats.contains(Format.FLAG)) { - String[] flagValues = attributeInfo.getFlagValues(); - if (flagValues != null) { - FlagXmlPropertyDialog dialog = - new FlagXmlPropertyDialog(propertyTable.getShell(), - "Select Flag Values", false /* radio */, - flagValues, xmlProperty); - - dialog.open(); - return; - } - } else if (formats.contains(Format.ENUM)) { - String[] enumValues = attributeInfo.getEnumValues(); - if (enumValues != null) { - FlagXmlPropertyDialog dialog = - new FlagXmlPropertyDialog(propertyTable.getShell(), - "Select Enum Value", true /* radio */, - enumValues, xmlProperty); - dialog.open(); - return; - } - } else { - for (Format format : formats) { - ResourceType t = format.getResourceType(); - if (t != null) { - if (type != null) { - if (types == null) { - types = new ArrayList<ResourceType>(); - types.add(type); - } - types.add(t); - } - type = t; - } else if (format == Format.REFERENCE) { - referenceAllowed = true; - } - } - } - if (types != null || referenceAllowed) { - // Multiple resource types (such as string *and* boolean): - // just use a reference chooser - GraphicalEditorPart graphicalEditor = xmlProperty.getGraphicalEditor(); - if (graphicalEditor != null) { - LayoutEditorDelegate delegate = graphicalEditor.getEditorDelegate(); - IProject project = delegate.getEditor().getProject(); - if (project != null) { - // get the resource repository for this project and the system resources. - ResourceRepository projectRepository = - ResourceManager.getInstance().getProjectResources(project); - Shell shell = AdtPlugin.getShell(); - ReferenceChooserDialog dlg = new ReferenceChooserDialog( - project, - projectRepository, - shell); - dlg.setPreviewHelper(new ResourcePreviewHelper(dlg, graphicalEditor)); - - String currentValue = (String) property.getValue(); - dlg.setCurrentResource(currentValue); - - if (dlg.open() == Window.OK) { - String resource = dlg.getCurrentResource(); - if (resource != null) { - // Returns null for cancel, "" for clear and otherwise a new value - if (resource.length() > 0) { - property.setValue(resource); - } else { - property.setValue(null); - } - } - } - - return; - } - } - } else if (type != null) { - // Single resource type: use a resource chooser - GraphicalEditorPart graphicalEditor = xmlProperty.getGraphicalEditor(); - if (graphicalEditor != null) { - String currentValue = (String) property.getValue(); - // TODO: Add validator factory? - String resource = ResourceChooser.chooseResource(graphicalEditor, - type, currentValue, null /* validator */); - // Returns null for cancel, "" for clear and otherwise a new value - if (resource != null) { - if (resource.length() > 0) { - property.setValue(resource); - } else { - property.setValue(null); - } - } - } - - return; - } - } - - // Fallback: Just use a plain string editor - StringXmlPropertyDialog dialog = - new StringXmlPropertyDialog(propertyTable.getShell(), property); - if (dialog.open() == Window.OK) { - // TODO: Do I need to activate? - } - } - - /** Qualified name for the per-project persistent property include-map */ - private final static QualifiedName CACHE_NAME = new QualifiedName(AdtPlugin.PLUGIN_ID, - "property-images");//$NON-NLS-1$ - - @NonNull - private static Map<String, Image> getImageCache(@NonNull Property property) { - XmlProperty xmlProperty = (XmlProperty) property; - GraphicalEditorPart graphicalEditor = xmlProperty.getGraphicalEditor(); - IProject project = graphicalEditor.getProject(); - try { - Map<String, Image> cache = (Map<String, Image>) project.getSessionProperty(CACHE_NAME); - if (cache == null) { - cache = Maps.newHashMap(); - project.setSessionProperty(CACHE_NAME, cache); - } - - return cache; - } catch (CoreException e) { - AdtPlugin.log(e, null); - return Maps.newHashMap(); - } - } -} |