diff options
Diffstat (limited to 'layoutlib_utils/src/com/android/ide/common')
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; +} |