This commit is contained in:
Alexander Lobas
2012-03-11 22:51:39 +04:00
parent 16ed488e7a
commit 9e35384b28
7 changed files with 167 additions and 95 deletions
@@ -18,7 +18,6 @@ package com.intellij.android.designer.designSurface;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.resources.configuration.*;
import com.android.sdklib.IAndroidTarget;
import com.intellij.android.designer.actions.ProfileAction;
import com.intellij.android.designer.componentTree.AndroidTreeDecorator;
import com.intellij.android.designer.model.ModelParser;
@@ -44,10 +43,8 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.ThrowableRunnable;
import org.jetbrains.android.dom.attrs.AttributeDefinitions;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.sdk.AndroidTargetData;
import org.jetbrains.android.uipreview.*;
import org.jetbrains.android.util.AndroidSdkNotConfiguredException;
import org.jetbrains.annotations.NonNls;
@@ -130,10 +127,10 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
createRenderer(parser.getLayoutXmlText(), new ThrowableRunnable<Throwable>() {
@Override
public void run() throws Throwable {
checkRenderer();
checkRenderer(false);
RootView rootView = new RootView(mySession.getImage(), 30, 20);
parser.updateRootComponent(mySession.getRootViews(), rootView);
parser.updateRootComponent(mySession, rootView);
new PropertyParser(myModule, myProfileAction.getProfileManager().getSelectedTarget()).loadRecursive(parser.getRootComponent());
@@ -160,20 +157,24 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
createRenderer(layoutXmlText, new ThrowableRunnable<Throwable>() {
@Override
public void run() throws Throwable {
checkRenderer();
RadViewComponent rootComponent = (RadViewComponent)myRootComponent;
RootView rootView = (RootView)rootComponent.getNativeComponent();
rootView.setImage(mySession.getImage());
ModelParser.updateRootComponent(rootComponent, mySession.getRootViews(), rootView);
myLayeredPane.repaint();
updateRenderer(false);
}
});
}
private void checkRenderer() throws Throwable {
Result result = mySession.getResult();
private void updateRenderer(boolean render) throws Throwable {
checkRenderer(render);
RadViewComponent rootComponent = (RadViewComponent)myRootComponent;
RootView rootView = (RootView)rootComponent.getNativeComponent();
rootView.setImage(mySession.getImage());
ModelParser.updateRootComponent(rootComponent, mySession, rootView);
myLayeredPane.repaint();
}
private void checkRenderer(boolean render) throws Throwable {
Result result = render ? mySession.render() : mySession.getResult();
if (!result.isSuccess()) {
System.out.println(
"No session: " + result.getErrorMessage() + " : " + result.getStatus() + " : " + result.getData() + " : " + result.getException());
@@ -250,6 +251,7 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
mySession = RenderUtil
.createRenderSession(getProject(), layoutXmlText, myFile, manager.getSelectedTarget(), facet, config, xdpi, ydpi,
manager.getSelectedTheme());
System.out.println(mySession + " | " + mySession.getClass());
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
@@ -347,25 +349,35 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
@Override
protected boolean execute(ThrowableRunnable<Exception> operation) {
try {
myPSIChangeListener.stop();
operation.run();
updateRenderer(true);
return true;
}
catch (Throwable e) {
showError("Execute command", e);
return false;
}
finally {
myPSIChangeListener.start();
}
}
@Override
protected void execute(List<EditOperation> operations) {
try {
myPSIChangeListener.stop();
for (EditOperation operation : operations) {
operation.execute();
}
updateRenderer(true);
}
catch (Throwable e) {
showError("Execute command", e);
}
finally {
myPSIChangeListener.start();
}
}
private static class RootView extends JComponent {
@@ -15,63 +15,120 @@
*/
package com.intellij.android.designer.model;
import com.intellij.designer.model.RadComponent;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.Result;
import com.intellij.designer.propertyTable.Property;
import com.intellij.designer.propertyTable.PropertyEditor;
import com.intellij.designer.propertyTable.PropertyRenderer;
import com.intellij.designer.propertyTable.editors.AbstractTextFieldEditor;
import com.intellij.designer.propertyTable.renderers.LabelPropertyRenderer;
import com.intellij.psi.xml.XmlTag;
import org.jetbrains.annotations.NonNls;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.xml.XmlAttribute;
import org.jetbrains.android.dom.attrs.AttributeDefinition;
import org.jetbrains.annotations.NotNull;
/**
* @author Alexander Lobas
*/
public class AttributeProperty extends Property {
public class AttributeProperty extends Property<RadViewComponent> {
private final LabelPropertyRenderer myRenderer = new LabelPropertyRenderer(null);
private final AttributeDefinition myDefinition;
private final PropertyEditor myEditor = new AbstractTextFieldEditor() {
@Override
public Object getValue() throws Exception {
return myTextField.getText();
}
};
@NotNull private final String myAttribute;
public AttributeProperty(Property parent, @NotNull @NonNls String name, @NotNull @NonNls String attribute) {
super(parent, name);
myAttribute = attribute;
public AttributeProperty(Property parent, @NotNull AttributeDefinition definition) {
super(parent, definition.getName());
myDefinition = definition;
}
@Override
public Object getValue(RadComponent component) throws Exception {
Object value = component.getClientProperty(myAttribute);
if (value != null) {
return value;
public Object getValue(RadViewComponent component) throws Exception {
Object value = null;
XmlAttribute attribute = getAttribute(component);
if (attribute != null) {
value = attribute.getValue();
}
XmlTag tag = ((RadViewComponent)component).getTag();
return tag == null ? null : tag.getAttributeValue(myAttribute);
}
@Override
public void setValue(RadComponent component, Object value) throws Exception {
component.putClientProperty(myAttribute, value);
}
@Override
public boolean isDefaultValue(RadComponent component) throws Exception {
XmlTag tag = ((RadViewComponent)component).getTag();
Object value = component.getClientProperty(myAttribute);
if (tag != null && value != null) {
return value.equals(tag.getAttributeValue(myAttribute));
if (value == null) {
Object viewObject = component.getViewInfo().getViewObject();
RenderSession session = component.getRoot().getClientProperty(ModelParser.SESSION);
Result result = session.getProperty(viewObject, myDefinition.getName());
if (result.isSuccess()) {
value = result.getData();
}
}
return true;
return value;
}
@Override
public void setDefaultValue(RadComponent component) throws Exception {
component.putClientProperty(myAttribute, null);
public void setValue(final RadViewComponent component, final Object value) throws Exception {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
component.getTag().setAttribute("android:" + myDefinition.getName(), (String)value);
}
});
Object viewObject = component.getViewInfo().getViewObject();
viewObject.getClass().getMethod("setBackgroundColor", int.class).invoke(viewObject, 0xEE09AA);
/*RenderSession session = component.getRoot().getClientProperty(ModelParser.SESSION);
Result result = session.setProperty(viewObject, myDefinition.getName(), (String)value);
if (!result.isSuccess()) {
System.out.println(
"No set property value(" +
myDefinition +
"): " +
result.getErrorMessage() +
" : " +
result.getStatus() +
" : " +
result.getData() +
" : " +
result.getException());
}*/
}
@Override
public boolean isDefaultValue(RadViewComponent component) throws Exception {
return getAttribute(component) == null;
}
@Override
public void setDefaultValue(RadViewComponent component) throws Exception {
final XmlAttribute attribute = getAttribute(component);
if (attribute != null) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
attribute.delete();
}
});
Object viewObject = component.getViewInfo().getViewObject();
RenderSession session = component.getRoot().getClientProperty(ModelParser.SESSION);
Result result = session.setProperty(viewObject, myDefinition.getName(), null);
if (!result.isSuccess()) {
System.out.println(
"No set default property value(" +
myDefinition +
"): " +
result.getErrorMessage() +
" : " +
result.getStatus() +
" : " +
result.getData() +
" : " +
result.getException());
}
}
}
private XmlAttribute getAttribute(RadViewComponent component) {
return component.getTag().getAttribute("android:" + myDefinition.getName());
}
@NotNull
@@ -15,6 +15,7 @@
*/
package com.intellij.android.designer.model;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.ViewInfo;
import com.intellij.designer.model.MetaManager;
import com.intellij.designer.model.MetaModel;
@@ -34,6 +35,8 @@ import java.util.List;
* @author Alexander Lobas
*/
public class ModelParser extends XmlRecursiveElementVisitor {
public static final String SESSION = "RENDER_LIB_SESSION";
private final MetaManager myMetaManager;
private final XmlFile myXmlFile;
private RadViewComponent myRootComponent;
@@ -121,29 +124,25 @@ public class ModelParser extends XmlRecursiveElementVisitor {
return myLayoutXmlText;
}
public void updateRootComponent(List<ViewInfo> views, JComponent nativeComponent) throws Exception {
public void updateRootComponent(RenderSession session, JComponent nativeComponent) throws Exception {
RadViewComponent rootComponent = myRootComponent;
if (views.size() == 1) {
if (session.getRootViews().size() == 1) {
RadViewComponent newRootComponent = createComponent(myXmlFile.getRootTag(), myMetaManager.getModelByTag("<root>"));
rootComponent.setParent(newRootComponent);
newRootComponent.getChildren().add(rootComponent);
updateComponent(rootComponent, views.get(0), nativeComponent, 0, 0);
newRootComponent.setNativeComponent(nativeComponent);
newRootComponent.setBounds(0, 0, nativeComponent.getWidth(), nativeComponent.getHeight());
myRootComponent = newRootComponent;
}
else {
updateRootComponent(rootComponent, views, nativeComponent);
myRootComponent = rootComponent = newRootComponent;
}
updateRootComponent(rootComponent, session, nativeComponent);
}
public static void updateRootComponent(RadViewComponent rootComponent,
List<ViewInfo> views,
RenderSession session,
JComponent nativeComponent) {
List<ViewInfo> views = session.getRootViews();
int size = views.size();
List<RadComponent> children = rootComponent.getChildren();
for (int i = 0; i < size; i++) {
@@ -152,6 +151,7 @@ public class ModelParser extends XmlRecursiveElementVisitor {
rootComponent.setNativeComponent(nativeComponent);
rootComponent.setBounds(0, 0, nativeComponent.getWidth(), nativeComponent.getHeight());
rootComponent.setClientProperty(SESSION, session);
}
private static void updateComponent(RadViewComponent component,
@@ -38,14 +38,13 @@ import java.util.*;
public class PropertyParser {
private AttributeDefinitions myDefinitions;
private ProjectClassLoader myClassLoader;
private Map<String, List<AttributeDefinition>> myCachedAttributes;
private Map<String, List<Property>> myCachedProperties;
public PropertyParser(Module module, IAndroidTarget target) throws Exception {
MetaManager metaManager = ViewsMetaManager.getInstance(module.getProject());
myCachedAttributes = (Map<String, List<AttributeDefinition>>)metaManager.getCache().get(target.hashString());
if (myCachedAttributes == null) {
myCachedAttributes = new HashMap<String, List<AttributeDefinition>>();
metaManager.getCache().put(target.hashString(), myCachedAttributes);
myCachedProperties = metaManager.getCache(target.hashString());
if (myCachedProperties == null) {
metaManager.setCache(target.hashString(), myCachedProperties = new HashMap<String, List<Property>>());
}
AndroidPlatform androidPlatform = AndroidPlatform.getInstance(module);
@@ -65,49 +64,47 @@ public class PropertyParser {
}
public void load(RadViewComponent component) throws Exception {
List<Property> properties = new ArrayList<Property>();
component.setProperties(properties);
ViewInfo info = component.getViewInfo();
if (info == null) {
return;
component.setProperties(Collections.<Property>emptyList());
}
List<AttributeDefinition> attributes = loadAttributes(myClassLoader.loadClass(info.getClassName()));
for (AttributeDefinition attribute : attributes) {
// TODO
else {
component.setProperties(load(myClassLoader.loadClass(info.getClassName())));
}
}
private List<AttributeDefinition> loadAttributes(Class<?> componentClass) {
private List<Property> load(Class<?> componentClass) {
String component = componentClass.getSimpleName();
List<AttributeDefinition> attributes = myCachedAttributes.get(component);
List<Property> properties = myCachedProperties.get(component);
if (attributes == null) {
attributes = new ArrayList<AttributeDefinition>();
if (properties == null) {
properties = new ArrayList<Property>();
StyleableDefinition attributeDefs = myDefinitions.getStyleableByName(component);
if (attributeDefs != null) {
attributes.addAll(attributeDefs.getAttributes());
StyleableDefinition definitions = myDefinitions.getStyleableByName(component);
if (definitions != null) {
for (AttributeDefinition definition : definitions.getAttributes()) {
properties.add(new AttributeProperty(null, definition));
// TODO
}
}
Class<?> superComponentClass = componentClass.getSuperclass();
if (superComponentClass != null) {
attributes.addAll(loadAttributes(superComponentClass));
properties.addAll(load(superComponentClass));
}
if (!attributes.isEmpty()) {
Collections.sort(attributes, new Comparator<AttributeDefinition>() {
if (!properties.isEmpty()) {
Collections.sort(properties, new Comparator<Property>() {
@Override
public int compare(AttributeDefinition a1, AttributeDefinition a2) {
return a1.getName().compareTo(a2.getName());
public int compare(Property p1, Property p2) {
return p1.getName().compareTo(p2.getName());
}
});
}
myCachedAttributes.put(component, attributes);
myCachedProperties.put(component, properties);
}
return attributes;
return properties;
}
}
@@ -121,8 +121,13 @@ public abstract class MetaManager {
myPaletteGroups.add(group);
}
public Map<Object, Object> getCache() {
return myCache;
@SuppressWarnings("unchecked")
public <K, V> Map<K, V> getCache(Object key) {
return (Map<K, V>)myCache.get(key);
}
public void setCache(Object key, Object value) {
myCache.put(key, value);
}
@Nullable
@@ -134,11 +134,12 @@ public abstract class RadComponent {
return Collections.emptyList();
}
public final Object getClientProperty(@NotNull Object key) {
return myClientProperties.get(key);
@SuppressWarnings("unchecked")
public final <T> T getClientProperty(@NotNull String key) {
return (T)myClientProperties.get(key);
}
public final void putClientProperty(@NotNull Object key, Object value) {
public final void setClientProperty(@NotNull Object key, Object value) {
myClientProperties.put(key, value);
}
@@ -26,7 +26,7 @@ import java.util.List;
/**
* @author Alexander Lobas
*/
public abstract class Property {
public abstract class Property<T extends RadComponent> {
private final Property myParent;
@NotNull private final String myName;
private boolean myImportant;
@@ -48,7 +48,7 @@ public abstract class Property {
return myParent;
}
public List<Property> getChildren(@Nullable RadComponent component) {
public List<Property> getChildren(@Nullable T component) {
return Collections.emptyList();
}
@@ -69,18 +69,18 @@ public abstract class Property {
//
//////////////////////////////////////////////////////////////////////////////////////////
public Object getValue(RadComponent component) throws Exception {
public Object getValue(T component) throws Exception {
return null;
}
public void setValue(RadComponent component, Object value) throws Exception {
public void setValue(T component, Object value) throws Exception {
}
public boolean isDefaultValue(RadComponent component) throws Exception {
public boolean isDefaultValue(T component) throws Exception {
return false;
}
public void setDefaultValue(RadComponent component) throws Exception {
public void setDefaultValue(T component) throws Exception {
}
public boolean availableFor(List<RadComponent> components) {