aboutsummaryrefslogtreecommitdiffstats
path: root/layoutlib_utils/src/com/android/ide/common
diff options
context:
space:
mode:
Diffstat (limited to 'layoutlib_utils/src/com/android/ide/common')
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/BasicLayoutScene.java58
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/DensityBasedResourceValue.java34
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutBridgeWrapper.java201
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutLibrary.java143
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/ResourceValue.java63
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/StyleResourceValue.java60
-rw-r--r--layoutlib_utils/src/com/android/ide/common/layoutlib/ValueResourceParser.java227
-rw-r--r--layoutlib_utils/src/com/android/ide/common/log/ILogger.java64
-rw-r--r--layoutlib_utils/src/com/android/ide/common/sdk/LoadStatus.java24
9 files changed, 874 insertions, 0 deletions
diff --git a/layoutlib_utils/src/com/android/ide/common/layoutlib/BasicLayoutScene.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/BasicLayoutScene.java
new file mode 100644
index 0000000..dfb3992
--- /dev/null
+++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/BasicLayoutScene.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.android.ide.common.layoutlib;
+
+import com.android.layoutlib.api.LayoutScene;
+import com.android.layoutlib.api.SceneResult;
+import com.android.layoutlib.api.ViewInfo;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * Basic LayoutScene returning a given {@link SceneResult}, {@link ViewInfo} and
+ * {@link BufferedImage}.
+ * <p/>
+ * All other methods are untouched from the base implementation provided by the API.
+ *
+ */
+public class BasicLayoutScene extends LayoutScene {
+
+ private final SceneResult mResult;
+ private final ViewInfo mRootViewInfo;
+ private final BufferedImage mImage;
+
+ public BasicLayoutScene(SceneResult result, ViewInfo rootViewInfo, BufferedImage image) {
+ mResult = result;
+ mRootViewInfo = rootViewInfo;
+ mImage = image;
+ }
+
+ @Override
+ public SceneResult getResult() {
+ return mResult;
+ }
+
+ @Override
+ public ViewInfo getRootView() {
+ return mRootViewInfo;
+ }
+
+ @Override
+ public BufferedImage getImage() {
+ return mImage;
+ }
+}
diff --git a/layoutlib_utils/src/com/android/ide/common/layoutlib/DensityBasedResourceValue.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/DensityBasedResourceValue.java
new file mode 100644
index 0000000..e1c0caa
--- /dev/null
+++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/DensityBasedResourceValue.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.android.ide.common.layoutlib;
+
+import com.android.layoutlib.api.IDensityBasedResourceValue;
+
+public class DensityBasedResourceValue extends ResourceValue implements IDensityBasedResourceValue {
+
+ private Density mDensity;
+
+ public DensityBasedResourceValue(String type, String name, String value, Density density,
+ boolean isFramework) {
+ super(type, name, value, isFramework);
+ mDensity = density;
+ }
+
+ public Density getDensity() {
+ return mDensity;
+ }
+}
diff --git a/layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutBridgeWrapper.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutBridgeWrapper.java
new file mode 100644
index 0000000..f4c99bd
--- /dev/null
+++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutBridgeWrapper.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.android.ide.common.layoutlib;
+
+import com.android.layoutlib.api.ILayoutBridge;
+import com.android.layoutlib.api.ILayoutResult;
+import com.android.layoutlib.api.LayoutBridge;
+import com.android.layoutlib.api.LayoutScene;
+import com.android.layoutlib.api.SceneParams;
+import com.android.layoutlib.api.SceneResult;
+import com.android.layoutlib.api.ViewInfo;
+import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Map;
+
+/**
+ * {@link LayoutBridge} wrapper around a {@link ILayoutBridge}.
+ * <p/>
+ * The goal is to let tools only uses the latest API by providing a conversion interface
+ * between the really old API ({@link ILayoutBridge}) and the new one ({@link ILayoutBridge}).
+ *
+ */
+@SuppressWarnings("deprecation")
+class LayoutBridgeWrapper extends LayoutBridge {
+
+ private final ILayoutBridge mBridge;
+ private final ClassLoader mClassLoader;
+
+ LayoutBridgeWrapper(ILayoutBridge bridge, ClassLoader classLoader) {
+ mBridge = bridge;
+ mClassLoader = classLoader;
+ }
+
+ @Override
+ public int getApiLevel() {
+ int apiLevel = 1;
+ try {
+ apiLevel = mBridge.getApiLevel();
+ } catch (AbstractMethodError e) {
+ // the first version of the api did not have this method
+ // so this is 1
+ }
+
+ return apiLevel;
+ }
+
+ @Override
+ public boolean init(String fontOsLocation, Map<String, Map<String, Integer>> enumValueMap) {
+ return mBridge.init(fontOsLocation, enumValueMap);
+ }
+
+ @Override
+ public boolean dispose() {
+ // there's no dispose in ILayoutBridge
+ return true;
+ }
+
+
+ @Override
+ public LayoutScene createScene(SceneParams params) {
+ int apiLevel = mBridge.getApiLevel();
+
+ ILayoutResult result = null;
+
+ if (apiLevel == 4) {
+ // Final ILayoutBridge API added support for "render full height"
+ result = mBridge.computeLayout(
+ params.getLayoutDescription(), params.getProjectKey(),
+ params.getScreenWidth(), params.getScreenHeight(), params.getRenderFullSize(),
+ params.getDensity(), params.getXdpi(), params.getYdpi(),
+ params.getThemeName(), params.getIsProjectTheme(),
+ params.getProjectResources(), params.getFrameworkResources(),
+ params.getProjectCallback(), params.getLogger());
+ } else if (apiLevel == 3) {
+ // api 3 add density support.
+ result = mBridge.computeLayout(
+ params.getLayoutDescription(), params.getProjectKey(),
+ params.getScreenWidth(), params.getScreenHeight(),
+ params.getDensity(), params.getXdpi(), params.getYdpi(),
+ params.getThemeName(), params.getIsProjectTheme(),
+ params.getProjectResources(), params.getFrameworkResources(),
+ params.getProjectCallback(), params.getLogger());
+ } else if (apiLevel == 2) {
+ // api 2 added boolean for separation of project/framework theme
+ result = mBridge.computeLayout(
+ params.getLayoutDescription(), params.getProjectKey(),
+ params.getScreenWidth(), params.getScreenHeight(),
+ params.getThemeName(), params.getIsProjectTheme(),
+ params.getProjectResources(), params.getFrameworkResources(),
+ params.getProjectCallback(), params.getLogger());
+ } else {
+ // First api with no density/dpi, and project theme boolean mixed
+ // into the theme name.
+
+ // change the string if it's a custom theme to make sure we can
+ // differentiate them
+ String themeName = params.getThemeName();
+ if (params.getIsProjectTheme()) {
+ themeName = "*" + themeName; //$NON-NLS-1$
+ }
+
+ result = mBridge.computeLayout(
+ params.getLayoutDescription(), params.getProjectKey(),
+ params.getScreenWidth(), params.getScreenHeight(),
+ themeName,
+ params.getProjectResources(), params.getFrameworkResources(),
+ params.getProjectCallback(), params.getLogger());
+ }
+
+ // clean up that is not done by the ILayoutBridge itself
+ cleanUp();
+
+ return convertToScene(result);
+ }
+
+
+ @Override
+ public void clearCaches(Object projectKey) {
+ mBridge.clearCaches(projectKey);
+ }
+
+ /**
+ * Converts a {@link ILayoutResult} to a {@link LayoutScene}.
+ */
+ private LayoutScene convertToScene(ILayoutResult result) {
+
+ SceneResult sceneResult;
+ ViewInfo rootViewInfo;
+
+ if (result.getSuccess() == ILayoutResult.SUCCESS) {
+ sceneResult = SceneResult.SUCCESS;
+ rootViewInfo = convertToViewInfo(result.getRootView());
+ } else {
+ sceneResult = new SceneResult(result.getErrorMessage());
+ rootViewInfo = null;
+ }
+
+ // create a BasicLayoutScene. This will return the given values but return the default
+ // implementation for all method.
+ // ADT should gracefully handle the default implementations of LayoutScene
+ return new BasicLayoutScene(sceneResult, rootViewInfo, result.getImage());
+ }
+
+ /**
+ * Converts a {@link ILayoutViewInfo} (and its children) to a {@link ViewInfo}.
+ */
+ private ViewInfo convertToViewInfo(ILayoutViewInfo view) {
+ // create the view info.
+ ViewInfo viewInfo = new ViewInfo(view.getName(), view.getViewKey(),
+ view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
+
+ // then convert the children
+ ILayoutViewInfo[] children = view.getChildren();
+ if (children != null) {
+ ArrayList<ViewInfo> convertedChildren = new ArrayList<ViewInfo>(children.length);
+ for (ILayoutViewInfo child : children) {
+ convertedChildren.add(convertToViewInfo(child));
+ }
+ viewInfo.setChildren(convertedChildren);
+ }
+
+ return viewInfo;
+ }
+
+ /**
+ * Post rendering clean-up that must be done here because it's not done in any layoutlib using
+ * {@link ILayoutBridge}.
+ */
+ private void cleanUp() {
+ try {
+ Class<?> looperClass = mClassLoader.loadClass("android.os.Looper"); //$NON-NLS-1$
+ Field threadLocalField = looperClass.getField("sThreadLocal"); //$NON-NLS-1$
+ if (threadLocalField != null) {
+ threadLocalField.setAccessible(true);
+ // get object. Field is static so no need to pass an object
+ ThreadLocal<?> threadLocal = (ThreadLocal<?>) threadLocalField.get(null);
+ if (threadLocal != null) {
+ threadLocal.remove();
+ }
+ }
+ } catch (Exception e) {
+ // do nothing.
+ }
+ }
+}
diff --git a/layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutLibrary.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutLibrary.java
new file mode 100644
index 0000000..5ec7ae5
--- /dev/null
+++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/LayoutLibrary.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.android.ide.common.layoutlib;
+
+import com.android.ide.common.log.ILogger;
+import com.android.ide.common.sdk.LoadStatus;
+import com.android.layoutlib.api.ILayoutBridge;
+import com.android.layoutlib.api.LayoutBridge;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+/**
+ * Class representing and allowing to load the layoutlib jar file.
+ */
+@SuppressWarnings("deprecation")
+public class LayoutLibrary {
+
+ public final static String CLASS_BRIDGE = "com.android.layoutlib.bridge.Bridge"; //$NON-NLS-1$
+
+ /** Link to the layout bridge */
+ private final LayoutBridge mBridge;
+ /** Status of the layoutlib.jar loading */
+ private final LoadStatus mStatus;
+ /** classloader used to load the jar file */
+ private final ClassLoader mClassLoader;
+
+ /**
+ * Returns the loaded {@link LayoutBridge} object or null if the loading failed.
+ */
+ public LayoutBridge getBridge() {
+ return mBridge;
+ }
+
+ /**
+ * Returns the {@link LoadStatus} of the loading of the layoutlib jar file.
+ */
+ public LoadStatus getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * Returns the classloader used to load the classes in the layoutlib jar file.
+ */
+ public ClassLoader getClassLoader() {
+ return mClassLoader;
+ }
+
+ /**
+ * Loads the layoutlib.jar file located at the given path and returns a {@link LayoutLibrary}
+ * object representing the result.
+ * <p/>
+ * If loading failed {@link #getStatus()} will reflect this, and {@link #getBridge()} will
+ * return null.
+ *
+ * @param layoutLibJarOsPath the path of the jar file
+ * @param log an optional log file.
+ * @return a {@link LayoutLibrary} object always.
+ */
+ public static LayoutLibrary load(String layoutLibJarOsPath, ILogger log) {
+
+ LoadStatus status = LoadStatus.LOADING;
+ LayoutBridge bridge = null;
+ ClassLoader classLoader = null;
+
+ try {
+ // get the URL for the file.
+ File f = new File(layoutLibJarOsPath);
+ if (f.isFile() == false) {
+ if (log != null) {
+ log.error(null, "layoutlib.jar is missing!"); //$NON-NLS-1$
+ }
+ } else {
+ URI uri = f.toURI();
+ URL url = uri.toURL();
+
+ // create a class loader. Because this jar reference interfaces
+ // that are in the editors plugin, it's important to provide
+ // a parent class loader.
+ classLoader = new URLClassLoader(
+ new URL[] { url },
+ LayoutLibrary.class.getClassLoader());
+
+ // load the class
+ Class<?> clazz = classLoader.loadClass(CLASS_BRIDGE);
+ if (clazz != null) {
+ // instantiate an object of the class.
+ Constructor<?> constructor = clazz.getConstructor();
+ if (constructor != null) {
+ Object bridgeObject = constructor.newInstance();
+ if (bridgeObject instanceof LayoutBridge) {
+ bridge = (LayoutBridge)bridgeObject;
+ } else if (bridgeObject instanceof ILayoutBridge) {
+ bridge = new LayoutBridgeWrapper((ILayoutBridge) bridgeObject,
+ classLoader);
+ }
+ }
+ }
+
+ if (bridge == null) {
+ status = LoadStatus.FAILED;
+ if (log != null) {
+ log.error(null, "Failed to load " + CLASS_BRIDGE); //$NON-NLS-1$
+ }
+ } else {
+ // mark the lib as loaded.
+ status = LoadStatus.LOADED;
+ }
+ }
+ } catch (Throwable t) {
+ status = LoadStatus.FAILED;
+ // log the error.
+ if (log != null) {
+ log.error(t, "Failed to load the LayoutLib");
+ }
+ }
+
+ return new LayoutLibrary(bridge, classLoader, status);
+ }
+
+ private LayoutLibrary(LayoutBridge bridge, ClassLoader classLoader, LoadStatus status) {
+ mBridge = bridge;
+ mClassLoader = classLoader;
+ mStatus = status;
+ }
+}
diff --git a/layoutlib_utils/src/com/android/ide/common/layoutlib/ResourceValue.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/ResourceValue.java
new file mode 100644
index 0000000..382d961
--- /dev/null
+++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/ResourceValue.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.android.ide.common.layoutlib;
+
+import com.android.layoutlib.api.IResourceValue;
+
+public class ResourceValue implements IResourceValue {
+ private final String mType;
+ private final String mName;
+ private String mValue = null;
+ private final boolean mIsFramwork;
+
+ public ResourceValue(String type, String name, boolean isFramwork) {
+ mType = type;
+ mName = name;
+ mIsFramwork = isFramwork;
+ }
+
+ public ResourceValue(String type, String name, String value, boolean isFramework) {
+ mType = type;
+ mName = name;
+ mValue = value;
+ mIsFramwork = isFramework;
+ }
+
+ public String getType() {
+ return mType;
+ }
+
+ public final String getName() {
+ return mName;
+ }
+
+ public final String getValue() {
+ return mValue;
+ }
+
+ public final void setValue(String value) {
+ mValue = value;
+ }
+
+ public void replaceWith(ResourceValue value) {
+ mValue = value.mValue;
+ }
+
+ public boolean isFramework() {
+ return mIsFramwork;
+ }
+}
diff --git a/layoutlib_utils/src/com/android/ide/common/layoutlib/StyleResourceValue.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/StyleResourceValue.java
new file mode 100644
index 0000000..721b16c
--- /dev/null
+++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/StyleResourceValue.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.android.ide.common.layoutlib;
+
+import com.android.layoutlib.api.IResourceValue;
+import com.android.layoutlib.api.IStyleResourceValue;
+
+import java.util.HashMap;
+
+public final class StyleResourceValue extends ResourceValue implements IStyleResourceValue {
+
+ private String mParentStyle = null;
+ private HashMap<String, IResourceValue> mItems = new HashMap<String, IResourceValue>();
+
+ public StyleResourceValue(String type, String name, boolean isFramework) {
+ super(type, name, isFramework);
+ }
+
+ public StyleResourceValue(String type, String name, String parentStyle, boolean isFramework) {
+ super(type, name, isFramework);
+ mParentStyle = parentStyle;
+ }
+
+ public String getParentStyle() {
+ return mParentStyle;
+ }
+
+ public IResourceValue findItem(String name) {
+ return mItems.get(name);
+ }
+
+ public void addItem(IResourceValue value) {
+ mItems.put(value.getName(), value);
+ }
+
+ @Override
+ public void replaceWith(ResourceValue value) {
+ super.replaceWith(value);
+
+ if (value instanceof StyleResourceValue) {
+ mItems.clear();
+ mItems.putAll(((StyleResourceValue)value).mItems);
+ }
+ }
+
+}
diff --git a/layoutlib_utils/src/com/android/ide/common/layoutlib/ValueResourceParser.java b/layoutlib_utils/src/com/android/ide/common/layoutlib/ValueResourceParser.java
new file mode 100644
index 0000000..c784f1f
--- /dev/null
+++ b/layoutlib_utils/src/com/android/ide/common/layoutlib/ValueResourceParser.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.android.ide.common.layoutlib;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * SAX handler to parser value resource files.
+ */
+public final class ValueResourceParser extends DefaultHandler {
+
+ // TODO: reuse definitions from somewhere else.
+ private final static String NODE_RESOURCES = "resources";
+ private final static String NODE_ITEM = "item";
+ private final static String ATTR_NAME = "name";
+ private final static String ATTR_TYPE = "type";
+ private final static String ATTR_PARENT = "parent";
+
+ // Resource type definition
+ private final static String RES_STYLE = "style";
+ private final static String RES_ATTR = "attr";
+
+ private final static String DEFAULT_NS_PREFIX = "android:";
+ private final static int DEFAULT_NS_PREFIX_LEN = DEFAULT_NS_PREFIX.length();
+
+ public interface IValueResourceRepository {
+ void addResourceValue(String resType, ResourceValue value);
+ }
+
+ private boolean inResources = false;
+ private int mDepth = 0;
+ private StyleResourceValue mCurrentStyle = null;
+ private ResourceValue mCurrentValue = null;
+ private IValueResourceRepository mRepository;
+ private final boolean mIsFramework;
+
+ public ValueResourceParser(IValueResourceRepository repository, boolean isFramework) {
+ mRepository = repository;
+ mIsFramework = isFramework;
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if (mCurrentValue != null) {
+ mCurrentValue.setValue(trimXmlWhitespaces(mCurrentValue.getValue()));
+ }
+
+ if (inResources && qName.equals(NODE_RESOURCES)) {
+ inResources = false;
+ } else if (mDepth == 2) {
+ mCurrentValue = null;
+ mCurrentStyle = null;
+ } else if (mDepth == 3) {
+ mCurrentValue = null;
+ }
+
+ mDepth--;
+ super.endElement(uri, localName, qName);
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes)
+ throws SAXException {
+ try {
+ mDepth++;
+ if (inResources == false && mDepth == 1) {
+ if (qName.equals(NODE_RESOURCES)) {
+ inResources = true;
+ }
+ } else if (mDepth == 2 && inResources == true) {
+ String type;
+
+ // if the node is <item>, we get the type from the attribute "type"
+ if (NODE_ITEM.equals(qName)) {
+ type = attributes.getValue(ATTR_TYPE);
+ } else {
+ // the type is the name of the node.
+ type = qName;
+ }
+
+ if (type != null) {
+ if (RES_ATTR.equals(type) == false) {
+ // get the resource name
+ String name = attributes.getValue(ATTR_NAME);
+ if (name != null) {
+ if (RES_STYLE.equals(type)) {
+ String parent = attributes.getValue(ATTR_PARENT);
+ mCurrentStyle = new StyleResourceValue(type, name, parent, mIsFramework);
+ mRepository.addResourceValue(type, mCurrentStyle);
+ } else {
+ mCurrentValue = new ResourceValue(type, name, mIsFramework);
+ mRepository.addResourceValue(type, mCurrentValue);
+ }
+ }
+ }
+ }
+ } else if (mDepth == 3 && mCurrentStyle != null) {
+ // get the resource name
+ String name = attributes.getValue(ATTR_NAME);
+ if (name != null) {
+ // the name can, in some cases, contain a prefix! we remove it.
+ if (name.startsWith(DEFAULT_NS_PREFIX)) {
+ name = name.substring(DEFAULT_NS_PREFIX_LEN);
+ }
+
+ mCurrentValue = new ResourceValue(null, name, mIsFramework);
+ mCurrentStyle.addItem(mCurrentValue);
+ }
+ }
+ } finally {
+ super.startElement(uri, localName, qName, attributes);
+ }
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ if (mCurrentValue != null) {
+ String value = mCurrentValue.getValue();
+ if (value == null) {
+ mCurrentValue.setValue(new String(ch, start, length));
+ } else {
+ mCurrentValue.setValue(value + new String(ch, start, length));
+ }
+ }
+ }
+
+ public static String trimXmlWhitespaces(String value) {
+ if (value == null) {
+ return null;
+ }
+
+ // look for carriage return and replace all whitespace around it by just 1 space.
+ int index;
+
+ while ((index = value.indexOf('\n')) != -1) {
+ // look for whitespace on each side
+ int left = index - 1;
+ while (left >= 0) {
+ if (Character.isWhitespace(value.charAt(left))) {
+ left--;
+ } else {
+ break;
+ }
+ }
+
+ int right = index + 1;
+ int count = value.length();
+ while (right < count) {
+ if (Character.isWhitespace(value.charAt(right))) {
+ right++;
+ } else {
+ break;
+ }
+ }
+
+ // remove all between left and right (non inclusive) and replace by a single space.
+ String leftString = null;
+ if (left >= 0) {
+ leftString = value.substring(0, left + 1);
+ }
+ String rightString = null;
+ if (right < count) {
+ rightString = value.substring(right);
+ }
+
+ if (leftString != null) {
+ value = leftString;
+ if (rightString != null) {
+ value += " " + rightString;
+ }
+ } else {
+ value = rightString != null ? rightString : "";
+ }
+ }
+
+ // now we un-escape the string
+ int length = value.length();
+ char[] buffer = value.toCharArray();
+
+ for (int i = 0 ; i < length ; i++) {
+ if (buffer[i] == '\\' && i + 1 < length) {
+ if (buffer[i+1] == 'u') {
+ if (i + 5 < length) {
+ // this is unicode char \u1234
+ int unicodeChar = Integer.parseInt(new String(buffer, i+2, 4), 16);
+
+ // put the unicode char at the location of the \
+ buffer[i] = (char)unicodeChar;
+
+ // offset the rest of the buffer since we go from 6 to 1 char
+ if (i + 6 < buffer.length) {
+ System.arraycopy(buffer, i+6, buffer, i+1, length - i - 6);
+ }
+ length -= 5;
+ }
+ } else {
+ if (buffer[i+1] == 'n') {
+ // replace the 'n' char with \n
+ buffer[i+1] = '\n';
+ }
+
+ // offset the buffer to erase the \
+ System.arraycopy(buffer, i+1, buffer, i, length - i - 1);
+ length--;
+ }
+ }
+ }
+
+ return new String(buffer, 0, length);
+ }
+}
diff --git a/layoutlib_utils/src/com/android/ide/common/log/ILogger.java b/layoutlib_utils/src/com/android/ide/common/log/ILogger.java
new file mode 100644
index 0000000..1ad602e
--- /dev/null
+++ b/layoutlib_utils/src/com/android/ide/common/log/ILogger.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.android.ide.common.log;
+
+import java.util.Formatter;
+
+public interface ILogger {
+
+ /**
+ * Prints a warning message on stdout.
+ * <p/>
+ * The message will be tagged with "Warning" on the output so the caller does not
+ * need to put such a prefix in the format string.
+ * <p/>
+ * Implementations should only display warnings in verbose mode.
+ *
+ * @param warningFormat is an optional error format. If non-null, it will be printed
+ * using a {@link Formatter} with the provided arguments.
+ * @param args provides the arguments for warningFormat.
+ */
+ void warning(String warningFormat, Object... args);
+
+ /**
+ * Prints an error message on stderr.
+ * <p/>
+ * The message will be tagged with "Error" on the output so the caller does not
+ * need to put such a prefix in the format string.
+ * <p/>
+ * Implementation should always display errors, independent of verbose mode.
+ *
+ * @param t is an optional {@link Throwable} or {@link Exception}. If non-null, it's
+ * message will be printed out.
+ * @param errorFormat is an optional error format. If non-null, it will be printed
+ * using a {@link Formatter} with the provided arguments.
+ * @param args provides the arguments for errorFormat.
+ */
+ void error(Throwable t, String errorFormat, Object... args);
+
+ /**
+ * Prints a message as-is on stdout.
+ * <p/>
+ * Implementation should always display errors, independent of verbose mode.
+ * No prefix is used, the message is printed as-is after formatting.
+ *
+ * @param msgFormat is an optional error format. If non-null, it will be printed
+ * using a {@link Formatter} with the provided arguments.
+ * @param args provides the arguments for msgFormat.
+ */
+ void printf(String msgFormat, Object... args);
+}
diff --git a/layoutlib_utils/src/com/android/ide/common/sdk/LoadStatus.java b/layoutlib_utils/src/com/android/ide/common/sdk/LoadStatus.java
new file mode 100644
index 0000000..babbd63
--- /dev/null
+++ b/layoutlib_utils/src/com/android/ide/common/sdk/LoadStatus.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.android.ide.common.sdk;
+
+/**
+ * Enum for loading status of various SDK parts.
+ */
+public enum LoadStatus {
+ LOADING, LOADED, FAILED;
+}