Properties

This commit is contained in:
Alexander Lobas
2012-04-05 15:49:09 +04:00
parent 022847c9e3
commit d44ec23a57
11 changed files with 312 additions and 103 deletions
@@ -18,10 +18,7 @@ package com.intellij.android.designer.model;
import com.android.ide.common.rendering.api.ViewInfo;
import com.android.resources.ResourceType;
import com.android.sdklib.IAndroidTarget;
import com.intellij.android.designer.propertyTable.AttributeProperty;
import com.intellij.android.designer.propertyTable.AttributePropertyWithDefault;
import com.intellij.android.designer.propertyTable.CompoundProperty;
import com.intellij.android.designer.propertyTable.FlagProperty;
import com.intellij.android.designer.propertyTable.*;
import com.intellij.android.designer.propertyTable.editors.ResourceDialog;
import com.intellij.designer.model.MetaManager;
import com.intellij.designer.model.MetaModel;
@@ -138,7 +135,7 @@ public class PropertyParser {
StyleableDefinition definitions = myDefinitions.getStyleableByName(component);
if (definitions != null) {
Property padding = null;
boolean padding = false;
for (AttributeDefinition definition : definitions.getAttributes()) {
String name = definition.getName();
@@ -146,10 +143,10 @@ public class PropertyParser {
Property property;
if ("padding".equals(name) && "View".equals(component)) {
property = padding = new CompoundProperty(name, definition);
padding = true;
}
else if (formats.contains(AttributeFormat.Flag)) {
property = new FlagProperty(name, definition, model);
if (formats.contains(AttributeFormat.Flag)) {
property = new FlagProperty(name, definition);
}
else {
property = new AttributeProperty(name, definition);
@@ -158,19 +155,21 @@ public class PropertyParser {
if (model != null) {
model.decorate(property, name);
}
properties.add(property);
}
if (padding != null) {
List<Property> children = padding.getChildren(null);
children.add(PropertyTable.extractProperty(properties, "paddingLeft"));
children.add(PropertyTable.extractProperty(properties, "paddingTop"));
children.add(PropertyTable.extractProperty(properties, "paddingRight"));
children.add(PropertyTable.extractProperty(properties, "paddingBottom"));
children.add(PropertyTable.extractProperty(properties, "paddingStart"));
children.add(PropertyTable.extractProperty(properties, "paddingEnd"));
if (padding) {
CompoundDimensionProperty paddingProperty = new CompoundDimensionProperty("padding");
moveProperties(properties, paddingProperty,
"padding", "all",
"paddingLeft", "left",
"paddingTop", "top",
"paddingRight", "right",
"paddingBottom", "bottom",
"paddingStart", "start",
"paddingEnd", "end");
paddingProperty.decorate(model);
properties.add(paddingProperty);
}
}
@@ -188,25 +187,7 @@ public class PropertyParser {
properties.add(superProperty);
}
else {
String name = superProperty.getName();
boolean normal = model.isNormalProperty(name);
boolean important = model.isImportantProperty(name);
boolean expert = model.isExpertProperty(name);
boolean deprecated = model.isDeprecatedProperty(name);
if ((normal && (superProperty.isImportant() || superProperty.isExpert())) ||
(important && !superProperty.isImportant()) ||
(expert && !superProperty.isExpert()) ||
(deprecated && !superProperty.isDeprecated())) {
Property property = superProperty.createForNewPresentation();
property.setImportant(important);
property.setExpert(expert);
property.setDeprecated(deprecated);
properties.add(property);
}
else {
properties.add(superProperty);
}
properties.add(model.decorateWithOverride(superProperty));
}
}
}
@@ -236,7 +217,7 @@ public class PropertyParser {
StyleableDefinition definitions = myDefinitions.getStyleableByName(component);
if (definitions != null) {
Property margin = null;
boolean margin = false;
for (AttributeDefinition definition : definitions.getAttributes()) {
String name = definition.getName();
@@ -244,7 +225,7 @@ public class PropertyParser {
Set<AttributeFormat> formats = definition.getFormats();
Property property;
if (name.startsWith(LAYOUT_MARGIN_PREFIX) && name.length() > LAYOUT_MARGIN_PREFIX.length()) {
if (name.startsWith(LAYOUT_MARGIN_PREFIX)) {
name = name.substring(LAYOUT_PREFIX.length());
important = false;
}
@@ -252,45 +233,54 @@ public class PropertyParser {
name = "layout:" + name.substring(LAYOUT_PREFIX.length());
}
if ("layout:margin".equals(name) && "ViewGroup_MarginLayout".equals(component)) {
property = margin = new CompoundProperty(name, definition);
if ("margin".equals(name) && "ViewGroup_MarginLayout".equals(component)) {
margin = true;
}
else if ("layout:width".equals(name) || "layout:height".equals(name)) {
if ("layout:width".equals(name) || "layout:height".equals(name)) {
property = new AttributePropertyWithDefault(name, definition, "wrap_content");
}
else if (formats.contains(AttributeFormat.Flag)) {
property = new FlagProperty(name, definition, model);
property = new FlagProperty(name, definition);
}
else {
property = new AttributeProperty(name, definition);
}
if (model != null) {
model.decorate(property, name);
}
property.setImportant(important);
properties.add(property);
}
if (margin != null) {
List<Property> children = margin.getChildren(null);
PropertyTable.moveProperty(properties, "marginLeft", children, -1);
PropertyTable.moveProperty(properties, "marginTop", children, -1);
PropertyTable.moveProperty(properties, "marginRight", children, -1);
PropertyTable.moveProperty(properties, "marginBottom", children, -1);
PropertyTable.moveProperty(properties, "marginStart", children, -1);
PropertyTable.moveProperty(properties, "marginEnd", children, -1);
if (margin) {
CompoundDimensionProperty marginProperty = new CompoundDimensionProperty("layout:margin");
moveProperties(properties, marginProperty,
"margin", "all",
"marginLeft", "left",
"marginTop", "top",
"marginRight", "right",
"marginBottom", "bottom",
"marginStart", "start",
"marginEnd", "end");
if (model != null) {
for (Property child : children) {
model.decorate(child, "layout:margin." + child.getName());
}
marginProperty.decorate(model);
}
marginProperty.setImportant(true);
properties.add(marginProperty);
}
}
if (++index < components.length) {
for (Property property : loadLayoutProperties(components, index, model)) {
if (PropertyTable.findProperty(properties, property) == -1) {
properties.add(property);
if (model == null) {
properties.add(property);
}
else {
property = model.decorateWithOverride(property);
properties.add(property);
}
}
}
}
@@ -313,6 +303,16 @@ public class PropertyParser {
return properties;
}
private static void moveProperties(List<Property> source, Property destination, String... names) {
List<Property> children = destination.getChildren(null);
for (int i = 0; i < names.length; i += 2) {
Property property = PropertyTable.extractProperty(source, names[i]);
if (property != null) {
children.add(property.createForNewPresentation(destination, names[i + 1]));
}
}
}
public boolean isAssignableFrom(MetaModel base, MetaModel test) {
try {
Class<?> baseClass = myClassLoader.loadClass(base.getTarget());
@@ -1012,8 +1012,8 @@
<palette title="FrameLayout" icon="/com/intellij/android/designer/icons/FrameLayout.png"
tooltip="FrameLayout is designed to block out an area on the screen to display a single item."/>
<properties important="foreground foregroundGravity"
expert="layout:gravity.fill layout:gravity.fill_horizontal layout:gravity.fill_vertical layout:gravity.clip_vertical layout:gravity.clip_horizontal layout:margin.marginStart layout:margin.marginEnd"
<properties important="foreground foregroundGravity layout:margin"
expert="layout:gravity.fill layout:gravity.fill_horizontal layout:gravity.fill_vertical layout:gravity.clip_vertical layout:gravity.clip_horizontal layout:margin.start layout:margin.end"
/>
<creation>
@@ -45,7 +45,11 @@ public class AttributeProperty extends Property<RadViewComponent> {
private final PropertyEditor myEditor;
public AttributeProperty(@NotNull String name, @NotNull AttributeDefinition definition) {
super(null, name);
this(null, name, definition);
}
public AttributeProperty(@Nullable Property parent, @NotNull String name, @NotNull AttributeDefinition definition) {
super(parent, name);
myDefinition = definition;
Set<AttributeFormat> formats = definition.getFormats();
@@ -76,8 +80,8 @@ public class AttributeProperty extends Property<RadViewComponent> {
}
@Override
public Property createForNewPresentation() {
return new AttributeProperty(getName(), myDefinition);
public Property<RadViewComponent> createForNewPresentation(@Nullable Property parent, @NotNull String name) {
return new AttributeProperty(parent, name, myDefinition);
}
@Override
@@ -16,9 +16,11 @@
package com.intellij.android.designer.propertyTable;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.designer.propertyTable.Property;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.android.dom.attrs.AttributeDefinition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Alexander Lobas
@@ -27,10 +29,22 @@ public class AttributePropertyWithDefault extends AttributeProperty {
private final String myDefaultValue;
public AttributePropertyWithDefault(@NotNull String name, @NotNull AttributeDefinition definition, @NotNull String defaultValue) {
super(name, definition);
this(null, name, definition, defaultValue);
}
public AttributePropertyWithDefault(@Nullable Property parent,
@NotNull String name,
@NotNull AttributeDefinition definition,
@NotNull String defaultValue) {
super(parent, name, definition);
myDefaultValue = defaultValue;
}
@Override
public Property<RadViewComponent> createForNewPresentation(@Nullable Property parent, @NotNull String name) {
return new AttributePropertyWithDefault(parent, name, myDefinition, myDefaultValue);
}
@Override
public boolean isDefaultValue(RadViewComponent component) throws Exception {
return myDefaultValue.equals(getValue(component));
@@ -0,0 +1,70 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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.intellij.android.designer.propertyTable;
import com.intellij.android.designer.propertyTable.renderers.ResourceRenderer;
import com.intellij.designer.propertyTable.PropertyRenderer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.SimpleTextAttributes;
import org.jetbrains.android.dom.attrs.AttributeFormat;
import org.jetbrains.annotations.NotNull;
import java.util.EnumSet;
/**
* @author Alexander Lobas
*/
public class CompoundDimensionProperty extends CompoundProperty {
private ResourceRenderer myRenderer = new ResourceRenderer(EnumSet.of(AttributeFormat.Dimension)) {
@Override
protected void formatValue(String value) {
myColoredComponent.append("[");
if (!StringUtil.isEmpty(value)) {
int index = 0;
for (String childValue : StringUtil.split(value, ",")) {
if (index++ > 0) {
myColoredComponent.append(", ");
}
childValue = childValue.trim();
if (childValue.length() > 0) {
if (childValue.equals("?")) {
myColoredComponent.append("?", SimpleTextAttributes.EXCLUDED_ATTRIBUTES);
}
else {
super.formatValue(childValue);
}
}
}
}
myColoredComponent.append("]");
}
};
public CompoundDimensionProperty(@NotNull String name) {
super(name);
}
@Override
protected CompoundProperty createForNewPresentation(@NotNull String name) {
return new CompoundDimensionProperty(name);
}
@NotNull
@Override
public PropertyRenderer getRenderer() {
return myRenderer;
}
}
@@ -16,8 +16,11 @@
package com.intellij.android.designer.propertyTable;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.designer.model.MetaModel;
import com.intellij.designer.propertyTable.IPropertyDecorator;
import com.intellij.designer.propertyTable.Property;
import org.jetbrains.android.dom.attrs.AttributeDefinition;
import com.intellij.designer.propertyTable.PropertyEditor;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -27,25 +30,81 @@ import java.util.List;
/**
* @author Alexander Lobas
*/
public class CompoundProperty extends AttributeProperty {
private List<Property> myChildren = new ArrayList<Property>();
public abstract class CompoundProperty extends Property<RadViewComponent> implements IPropertyDecorator {
private List<Property<RadViewComponent>> myChildren = new ArrayList<Property<RadViewComponent>>();
public CompoundProperty(@NotNull String name, @NotNull AttributeDefinition definition) {
super(name, definition);
public CompoundProperty(@NotNull String name) {
super(null, name);
}
@Override
public List<Property> getChildren(@Nullable RadViewComponent component) {
return myChildren;
}
@Override
public Property createForNewPresentation() {
CompoundProperty property = new CompoundProperty(getName(), myDefinition);
List<Property> children = property.getChildren(null);
for (Property childProperty : myChildren) {
children.add(childProperty.createForNewPresentation());
public Property<RadViewComponent> createForNewPresentation(@Nullable Property parent, @NotNull String name) {
CompoundProperty property = createForNewPresentation(name);
List<Property<RadViewComponent>> children = property.getChildren(null);
for (Property<RadViewComponent> childProperty : myChildren) {
children.add(childProperty.createForNewPresentation(property, childProperty.getName()));
}
return property;
}
public void decorate(@NotNull MetaModel model) {
String name = getName();
model.decorate0(this, name);
for (Property<RadViewComponent> childProperty : myChildren) {
model.decorate(childProperty, name + "." + childProperty.getName());
}
}
@Override
public List<Property<RadViewComponent>> getChildren(@Nullable RadViewComponent component) {
return myChildren;
}
protected abstract CompoundProperty createForNewPresentation(@NotNull String name);
@Override
public Object getValue(RadViewComponent component) throws Exception {
StringBuilder value = new StringBuilder();
int index = 0;
int empty = 0;
for (Property<RadViewComponent> childProperty : myChildren) {
if (index++ > 0) {
value.append(", ");
}
String childValue = (String)childProperty.getValue(component);
if (StringUtil.isEmpty(childValue)) {
empty++;
value.append("?");
}
else {
value.append(childValue);
}
}
if (empty == myChildren.size()) {
return "";
}
return value.toString();
}
@Override
public boolean isDefaultValue(RadViewComponent component) throws Exception {
for (Property<RadViewComponent> childProperty : myChildren) {
if (!childProperty.isDefaultValue(component)) {
return false;
}
}
return true;
}
@Override
public void setDefaultValue(RadViewComponent component) throws Exception {
for (Property<RadViewComponent> childProperty : myChildren) {
childProperty.setDefaultValue(component);
}
}
@Override
public PropertyEditor getEditor() {
return null;
}
}
@@ -17,6 +17,7 @@ package com.intellij.android.designer.propertyTable;
import com.intellij.android.designer.model.RadViewComponent;
import com.intellij.designer.model.MetaModel;
import com.intellij.designer.propertyTable.IPropertyDecorator;
import com.intellij.designer.propertyTable.Property;
import com.intellij.designer.propertyTable.PropertyEditor;
import com.intellij.designer.propertyTable.PropertyRenderer;
@@ -35,39 +36,41 @@ import java.util.*;
/**
* @author Alexander Lobas
*/
public class FlagProperty extends Property<RadViewComponent> {
public class FlagProperty extends Property<RadViewComponent> implements IPropertyDecorator {
private final PropertyRenderer myRenderer = new LabelPropertyRenderer(null);
private final AttributeDefinition myDefinition;
private final List<Property> myOptions = new ArrayList<Property>();
private final List<Property<RadViewComponent>> myOptions = new ArrayList<Property<RadViewComponent>>();
public FlagProperty(@NotNull String name, @NotNull AttributeDefinition definition, @Nullable MetaModel model) {
public FlagProperty(@NotNull String name, @NotNull AttributeDefinition definition) {
super(null, name);
myDefinition = definition;
for (String option : definition.getValues()) {
myOptions.add(new OptionProperty(this, option, option));
}
}
if (model != null) {
for (Property option : myOptions) {
model.decorate(option, name + "." + option.getName());
}
@Override
public Property<RadViewComponent> createForNewPresentation(@Nullable Property parent, @NotNull String name) {
return new FlagProperty(name, myDefinition);
}
@Override
public void decorate(@NotNull MetaModel model) {
String name = getName();
for (Property option : myOptions) {
model.decorate(option, name + "." + option.getName());
}
}
@Override
public Property createForNewPresentation() {
return new FlagProperty(getName(), myDefinition, null);
}
@Override
public List<Property> getChildren(@Nullable RadViewComponent component) {
public List<Property<RadViewComponent>> getChildren(@Nullable RadViewComponent component) {
return myOptions;
}
@Override
public Object getValue(RadViewComponent component) throws Exception {
StringBuffer value = new StringBuffer("[");
StringBuilder value = new StringBuilder("[");
Set<String> options = getOptions(component);
int index = 0;
for (Property option : myOptions) {
@@ -158,6 +161,12 @@ public class FlagProperty extends Property<RadViewComponent> {
});
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Option
//
//////////////////////////////////////////////////////////////////////////////////////////
private class OptionProperty extends Property<RadViewComponent> {
private PropertyRenderer myRenderer = new BooleanRenderer();
private PropertyEditor myEditor = new BooleanEditor();
@@ -173,7 +182,7 @@ public class FlagProperty extends Property<RadViewComponent> {
}
@Override
public Property createForNewPresentation() {
public Property<RadViewComponent> createForNewPresentation(@Nullable Property parent, @NotNull String name) {
return null;
}
@@ -41,7 +41,7 @@ public class ResourceRenderer implements PropertyRenderer {
private final ColorIcon myColorIcon = new ColorIcon(10, 9);
private BooleanRenderer myBooleanRenderer;
private final SimpleColoredComponent myColoredComponent;
protected final SimpleColoredComponent myColoredComponent;
private final Set<AttributeFormat> myFormats;
public ResourceRenderer(Set<AttributeFormat> formats) {
@@ -75,6 +75,12 @@ public class ResourceRenderer implements PropertyRenderer {
myColoredComponent.setBackground(UIUtil.getTableBackground());
}
formatValue(value);
return myColoredComponent;
}
protected void formatValue(String value) {
if (!StringUtil.isEmpty(value)) {
int prefix = -1;
if (value.startsWith("#")) {
@@ -113,8 +119,6 @@ public class ResourceRenderer implements PropertyRenderer {
}
}
}
return myColoredComponent;
}
@Override
@@ -16,6 +16,7 @@
package com.intellij.designer.model;
import com.intellij.designer.palette.Item;
import com.intellij.designer.propertyTable.IPropertyDecorator;
import com.intellij.designer.propertyTable.Property;
import com.intellij.openapi.util.IconLoader;
import org.jetbrains.annotations.NotNull;
@@ -114,10 +115,6 @@ public class MetaModel {
myPaletteItem.setMetaModel(this);
}
public boolean isNormalProperty(String name) {
return myNormalProperties.contains(name);
}
public void setNormalProperties(List<String> normalProperties) {
myNormalProperties = normalProperties;
}
@@ -146,9 +143,31 @@ public class MetaModel {
myDeprecatedProperties = deprecatedProperties;
}
public void decorate(Property property, String name) {
public void decorate0(Property property, String name) {
property.setImportant(isImportantProperty(name));
property.setExpert(isExpertProperty(name));
property.setDeprecated(isDeprecatedProperty(name));
}
public void decorate(Property property, String name) {
decorate0(property, name);
if (property instanceof IPropertyDecorator) {
((IPropertyDecorator)property).decorate(this);
}
}
public Property decorateWithOverride(Property property) {
String name = property.getName();
if (myNormalProperties.contains(name) ||
myImportantProperties.contains(name) ||
myExpertProperties.contains(name) ||
myDeprecatedProperties.contains(name)) {
property = property.createForNewPresentation();
decorate(property, name);
}
return property;
}
}
@@ -0,0 +1,26 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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.intellij.designer.propertyTable;
import com.intellij.designer.model.MetaModel;
import org.jetbrains.annotations.NotNull;
/**
* @author Alexander Lobas
*/
public interface IPropertyDecorator {
void decorate(@NotNull MetaModel model);
}
@@ -37,7 +37,11 @@ public abstract class Property<T extends RadComponent> {
myName = name;
}
public abstract Property createForNewPresentation();
public Property<T> createForNewPresentation() {
return createForNewPresentation(myParent, myName);
}
public abstract Property<T> createForNewPresentation(@Nullable Property parent, @NotNull String name);
//////////////////////////////////////////////////////////////////////////////////////////
//
// Hierarchy
@@ -48,7 +52,7 @@ public abstract class Property<T extends RadComponent> {
return myParent;
}
public List<Property> getChildren(@Nullable T component) {
public List<Property<T>> getChildren(@Nullable T component) {
return Collections.emptyList();
}