Parse add-on supplied layout devices.

Add-ons are expected to provide a file called devices.xml in their root
folder. The XML schema for this file is
	eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/layout-configs.xsd

I slightly fixed the schema so that normal screen size use the token
"normal" instead of "medium" to match the resource qualifier.

To round up the feature, the following changes are included:
- getEnum in the resource qualifier enum has been made public. There's no
sense in keeping it private and it'll help with people possibly using
valueOf which behaves differently (case sensitive so
ScreenSize.valueOf("normal") fails, while getEnum on the same string succeed.
- Updated the device configuration UI to deal with missing list of
devices while the SDK loads.

Change-Id: Ib1b01007d2ae7fd6398172c3549b2686c33d48be
This commit is contained in:
Xavier Ducrohet
2009-09-27 21:39:07 -07:00
parent 3a68366197
commit 98b9c10e63
20 changed files with 496 additions and 155 deletions

View File

@@ -1026,10 +1026,16 @@ public class AdtPlugin extends AbstractUIPlugin {
progress.setTaskName(Messages.AdtPlugin_Parsing_Resources);
int n = sdk.getTargets().length;
final IAndroidTarget[] targets = sdk.getTargets();
final int n = targets.length;
if (n > 0) {
// load the layout devices.
sdk.parseAddOnLayoutDevices();
// load the rest of the targes.
// TODO: make this on-demand.
int w = 60 / n;
for (IAndroidTarget target : sdk.getTargets()) {
for (IAndroidTarget target : targets) {
SubMonitor p2 = progress.newChild(w);
IStatus status = new AndroidTargetParser(target).run(p2);
if (status.getCode() != IStatus.OK) {

View File

@@ -975,6 +975,7 @@ public class GraphicalEditorPart extends EditorPart implements IGraphicalLayoutE
AndroidTargetData data = currentSdk.getTargetData(target);
if (data != null) {
LayoutBridge bridge = data.getLayoutBridge();
mConfigComposite.reloadDevices();
mConfigComposite.setClippingSupport(bridge.apiLevel >= 4);
}
}

View File

@@ -738,6 +738,7 @@ public class GraphicalLayoutEditor extends GraphicalEditorWithPalette
AndroidTargetData data = currentSdk.getTargetData(target);
if (data != null) {
LayoutBridge bridge = data.getLayoutBridge();
mConfigComposite.reloadDevices();
mConfigComposite.setClippingSupport(bridge.apiLevel >= 4);
}
}

View File

@@ -28,6 +28,7 @@ import com.android.ide.eclipse.adt.internal.resources.configurations.VersionQual
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier.ScreenOrientation;
import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
import com.android.ide.eclipse.adt.internal.sdk.DeviceConfiguration;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.LanguageRegionVerifier;
import com.android.layoutlib.api.IResourceValue;
import com.android.layoutlib.api.IStyleResourceValue;
@@ -46,6 +47,7 @@ import org.eclipse.swt.widgets.Label;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
@@ -73,7 +75,7 @@ public class ConfigurationComposite extends Composite {
/** The {@link FolderConfiguration} representing the state of the UI controls */
private final FolderConfiguration mCurrentConfig = new FolderConfiguration();
private DeviceConfiguration[] mDevices;
private List<DeviceConfiguration> mDevices;
private final ArrayList<ResourceQualifier[] > mLocaleList =
new ArrayList<ResourceQualifier[]>();
@@ -103,7 +105,9 @@ public class ConfigurationComposite extends Composite {
public ConfigurationComposite(IConfigListener listener, Composite parent, int style) {
super(parent, style);
mListener = listener;
mDevices = DeviceConfiguration.getDevices();
if (Sdk.getCurrent() != null) {
mDevices = Sdk.getCurrent().getLayoutDevices();
}
GridLayout gl;
GridData gd;
@@ -141,12 +145,6 @@ public class ConfigurationComposite extends Composite {
new Label(this, SWT.NONE).setText("Devices");
mDeviceList = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
// fill with the devices
for (DeviceConfiguration device : mDevices) {
mDeviceList.add(device.getName());
}
mDeviceList.select(0);
mDeviceList.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
mDeviceList.addSelectionListener(new SelectionAdapter() {
@@ -158,15 +156,6 @@ public class ConfigurationComposite extends Composite {
new Label(this, SWT.NONE).setText("Config");
mDeviceConfigs = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
Map<String, FolderConfiguration> configs = mDevices[0].getConfigs();
Set<String> configNames = configs.keySet();
for (String name : configNames) {
mDeviceConfigs.add(name);
}
mDeviceConfigs.select(0);
if (configNames.size() == 1) {
mDeviceConfigs.setEnabled(false);
}
mDeviceConfigs.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
mDeviceConfigs.addSelectionListener(new SelectionAdapter() {
@@ -224,9 +213,12 @@ public class ConfigurationComposite extends Composite {
}
});
initUiWithDevices();
onDeviceConfigChange();
}
public FolderConfiguration getCurrentConfig() {
return mCurrentConfig;
}
@@ -457,6 +449,44 @@ public class ConfigurationComposite extends Composite {
mDisableUpdates = false;
}
/**
* Reloads the list of {@link DeviceConfiguration} from the {@link Sdk}.
*/
public void reloadDevices() {
mDevices = Sdk.getCurrent().getLayoutDevices();
initUiWithDevices();
onDeviceChange();
}
/**
* Init the UI with the list of Devices.
*/
private void initUiWithDevices() {
// remove older devices if applicable
mDeviceList.removeAll();
mDeviceConfigs.removeAll();
// fill with the devices
if (mDevices != null) {
for (DeviceConfiguration device : mDevices) {
mDeviceList.add(device.getName());
}
mDeviceList.select(0);
if (mDevices.size() > 0) {
Map<String, FolderConfiguration> configs = mDevices.get(0).getConfigs();
Set<String> configNames = configs.keySet();
for (String name : configNames) {
mDeviceConfigs.add(name);
}
mDeviceConfigs.select(0);
if (configNames.size() == 1) {
mDeviceConfigs.setEnabled(false);
}
}
}
}
/**
* Call back for language combo selection
*/
@@ -481,7 +511,7 @@ public class ConfigurationComposite extends Composite {
private void onDeviceChange() {
int deviceIndex = mDeviceList.getSelectionIndex();
DeviceConfiguration device = mDevices[deviceIndex];
DeviceConfiguration device = mDevices.get(deviceIndex);
mDeviceConfigs.removeAll();
@@ -499,28 +529,30 @@ public class ConfigurationComposite extends Composite {
}
private void onDeviceConfigChange() {
int deviceIndex = mDeviceList.getSelectionIndex();
DeviceConfiguration device = mDevices[deviceIndex];
if (mDevices != null) {
int deviceIndex = mDeviceList.getSelectionIndex();
DeviceConfiguration device = mDevices.get(deviceIndex);
int configIndex = mDeviceConfigs.getSelectionIndex();
String name = mDeviceConfigs.getItem(configIndex);
FolderConfiguration config = device.getConfigs().get(name);
int configIndex = mDeviceConfigs.getSelectionIndex();
String name = mDeviceConfigs.getItem(configIndex);
FolderConfiguration config = device.getConfigs().get(name);
// get the current qualifiers from the current config
LanguageQualifier lang = mCurrentConfig.getLanguageQualifier();
RegionQualifier region = mCurrentConfig.getRegionQualifier();
VersionQualifier version = mCurrentConfig.getVersionQualifier();
// get the current qualifiers from the current config
LanguageQualifier lang = mCurrentConfig.getLanguageQualifier();
RegionQualifier region = mCurrentConfig.getRegionQualifier();
VersionQualifier version = mCurrentConfig.getVersionQualifier();
// replace the config with the one from the device
mCurrentConfig.set(config);
// replace the config with the one from the device
mCurrentConfig.set(config);
// and put back the rest of the qualifiers
mCurrentConfig.addQualifier(lang);
mCurrentConfig.addQualifier(region);
mCurrentConfig.addQualifier(version);
// and put back the rest of the qualifiers
mCurrentConfig.addQualifier(lang);
mCurrentConfig.addQualifier(region);
mCurrentConfig.addQualifier(version);
if (mListener != null) {
mListener.onConfigurationChange();
if (mListener != null) {
mListener.onConfigurationChange();
}
}
}
@@ -603,3 +635,4 @@ public class ConfigurationComposite extends Composite {
return false;
}
}

View File

@@ -53,7 +53,7 @@ public final class KeyboardStateQualifier extends ResourceQualifier {
* @param value The qualifier value.
* @return the enum for the qualifier value or null if no matching was found.
*/
static KeyboardState getEnum(String value) {
public static KeyboardState getEnum(String value) {
for (KeyboardState orient : values()) {
if (orient.mValue.equals(value)) {
return orient;

View File

@@ -54,7 +54,7 @@ public final class NavigationMethodQualifier extends ResourceQualifier {
* @param value The qualifier value.
* @return the enum for the qualifier value or null if no matching was found.
*/
static NavigationMethod getEnum(String value) {
public static NavigationMethod getEnum(String value) {
for (NavigationMethod orient : values()) {
if (orient.mValue.equals(value)) {
return orient;

View File

@@ -61,7 +61,7 @@ public final class PixelDensityQualifier extends ResourceQualifier {
* @param value The qualifier value.
* @return the enum for the qualifier value or null if no matching was found.
*/
static Density getEnum(String value) {
public static Density getEnum(String value) {
for (Density orient : values()) {
if (orient.mValue.equals(value)) {
return orient;

View File

@@ -51,7 +51,7 @@ public final class ScreenOrientationQualifier extends ResourceQualifier {
* @param value The qualifier value.
* @return the enum for the qualifier value or null if no matching was found.
*/
static ScreenOrientation getEnum(String value) {
public static ScreenOrientation getEnum(String value) {
for (ScreenOrientation orient : values()) {
if (orient.mValue.equals(value)) {
return orient;

View File

@@ -48,7 +48,7 @@ public class ScreenRatioQualifier extends ResourceQualifier {
* @param value The qualifier value.
* @return the enum for the qualifier value or null if no matching was found.
*/
static ScreenRatio getEnum(String value) {
public static ScreenRatio getEnum(String value) {
for (ScreenRatio orient : values()) {
if (orient.mValue.equals(value)) {
return orient;

View File

@@ -52,7 +52,7 @@ public class ScreenSizeQualifier extends ResourceQualifier {
* @param value The qualifier value.
* @return the enum for the qualifier value or null if no matching was found.
*/
static ScreenSize getEnum(String value) {
public static ScreenSize getEnum(String value) {
for (ScreenSize orient : values()) {
if (orient.mValue.equals(value)) {
return orient;

View File

@@ -54,7 +54,7 @@ public final class TextInputMethodQualifier extends ResourceQualifier {
* @param value The qualifier value.
* @return the enum for the qualifier value or null if no matching was found.
*/
static TextInputMethod getEnum(String value) {
public static TextInputMethod getEnum(String value) {
for (TextInputMethod orient : values()) {
if (orient.mValue.equals(value)) {
return orient;

View File

@@ -52,7 +52,7 @@ public final class TouchScreenQualifier extends ResourceQualifier {
* @param value The qualifier value.
* @return the enum for the qualifier value or null if no matching was found.
*/
static TouchScreenType getEnum(String value) {
public static TouchScreenType getEnum(String value) {
for (TouchScreenType orient : values()) {
if (orient.mValue.equals(value)) {
return orient;

View File

@@ -17,23 +17,6 @@
package com.android.ide.eclipse.adt.internal.sdk;
import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenDimensionQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier.KeyboardState;
import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier.NavigationMethod;
import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier.Density;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier.ScreenOrientation;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier.ScreenRatio;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier.ScreenSize;
import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier.TextInputMethod;
import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier.TouchScreenType;
import java.util.Collections;
import java.util.HashMap;
@@ -64,66 +47,4 @@ public class DeviceConfiguration {
public Map<String, FolderConfiguration> getConfigs() {
return mMap;
}
/**
* temp method returning some hard-coded devices.
* TODO: load devices from the SDK and add-ons and remove this method.
*/
public static DeviceConfiguration[] getDevices() {
DeviceConfiguration adp1 = new DeviceConfiguration("ADP1");
// default config
FolderConfiguration defConfig = new FolderConfiguration();
defConfig.addQualifier(new ScreenSizeQualifier(ScreenSize.NORMAL));
defConfig.addQualifier(new ScreenRatioQualifier(ScreenRatio.NOTLONG));
defConfig.addQualifier(new PixelDensityQualifier(Density.MEDIUM));
defConfig.addQualifier(new TouchScreenQualifier(TouchScreenType.FINGER));
defConfig.addQualifier(new TextInputMethodQualifier(TextInputMethod.QWERTY));
defConfig.addQualifier(new NavigationMethodQualifier(NavigationMethod.TRACKBALL));
defConfig.addQualifier(new ScreenDimensionQualifier(480, 320));
// specific configs
FolderConfiguration closedLand = new FolderConfiguration();
closedLand.set(defConfig);
closedLand.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
closedLand.addQualifier(new KeyboardStateQualifier(KeyboardState.HIDDEN));
adp1.addConfig("Closed, landscape", closedLand);
FolderConfiguration closedPort = new FolderConfiguration();
closedPort.set(defConfig);
closedPort.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.PORTRAIT));
closedPort.addQualifier(new KeyboardStateQualifier(KeyboardState.HIDDEN));
adp1.addConfig("Closed, portrait", closedPort);
FolderConfiguration opened = new FolderConfiguration();
opened.set(defConfig);
opened.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
opened.addQualifier(new KeyboardStateQualifier(KeyboardState.EXPOSED));
adp1.addConfig("Opened", opened);
DeviceConfiguration ion = new DeviceConfiguration("Ion");
// default config
defConfig = new FolderConfiguration();
defConfig.addQualifier(new ScreenSizeQualifier(ScreenSize.NORMAL));
defConfig.addQualifier(new ScreenRatioQualifier(ScreenRatio.NOTLONG));
defConfig.addQualifier(new PixelDensityQualifier(Density.MEDIUM));
defConfig.addQualifier(new TouchScreenQualifier(TouchScreenType.FINGER));
defConfig.addQualifier(new KeyboardStateQualifier(KeyboardState.EXPOSED));
defConfig.addQualifier(new TextInputMethodQualifier(TextInputMethod.NOKEY));
defConfig.addQualifier(new NavigationMethodQualifier(NavigationMethod.TRACKBALL));
defConfig.addQualifier(new ScreenDimensionQualifier(480, 320));
// specific configs
FolderConfiguration landscape = new FolderConfiguration();
landscape.set(defConfig);
landscape.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
ion.addConfig("Landscape", landscape);
FolderConfiguration portrait = new FolderConfiguration();
portrait.set(defConfig);
portrait.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.PORTRAIT));
ion.addConfig("Portrait", portrait);
return new DeviceConfiguration[] { adp1, ion };
}
}
}

View File

@@ -17,10 +17,19 @@
package com.android.ide.eclipse.adt.internal.sdk;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import java.io.InputStream;
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
/**
* Public constants for the sdk-repository XML Schema.
* Public constants for the layout device description XML Schema.
*/
public class LayoutConfigsXsd {
@@ -100,4 +109,17 @@ public class LayoutConfigsXsd {
return LayoutConfigsXsd.class.getResourceAsStream("layout-configs.xsd"); //$NON-NLS-1$
}
/** Helper method that returns a {@link Validator} for our XSD */
public static Validator getValidator(ErrorHandler handler) throws SAXException {
InputStream xsdStream = getXsdStream();
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(new StreamSource(xsdStream));
Validator validator = schema.newValidator();
if (handler != null) {
validator.setErrorHandler(handler);
}
return validator;
}
}

View File

@@ -0,0 +1,165 @@
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Eclipse Public License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.eclipse.org/org/documents/epl-v10.php
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ide.eclipse.adt.internal.sdk;
import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenDimensionQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier.KeyboardState;
import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier.NavigationMethod;
import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier.Density;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier.ScreenOrientation;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier.ScreenRatio;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier.ScreenSize;
import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier.TextInputMethod;
import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier.TouchScreenType;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.util.ArrayList;
import java.util.List;
/**
* {@link DefaultHandler} implementation to parse Layout Device XML file.
* @see LayoutConfigsXsd
* @see Layout-configs.xsd
*/
class LayoutDeviceHandler extends DefaultHandler {
/*
* The handler does most of the work in startElement and endElement.
* In startElement, it'll create DeviceConfiguration on <device>, as well as
* FolderConfiguration instances on <default> and <config>.
* Those objects are then filled as new nodes are discovered.
*
* For the qualifier values, the qualifier is created and added to the current config
* on the endElement, by using the content found in characters().
*/
private List<DeviceConfiguration> mDevices = new ArrayList<DeviceConfiguration>();
private DeviceConfiguration mCurrentDevice;
private FolderConfiguration mDefaultConfig;
private FolderConfiguration mCurrentConfig;
private final StringBuilder mStringAccumulator = new StringBuilder();
private String mSize1, mSize2;
public List<DeviceConfiguration> getDevices() {
return mDevices;
}
@Override
public void startElement(String uri, String localName, String name, Attributes attributes)
throws SAXException {
if (LayoutConfigsXsd.NODE_DEVICE.equals(localName)) {
// get the deviceName, will not be null since we validated the XML.
String deviceName = attributes.getValue("", LayoutConfigsXsd.ATTR_NAME);
// create a device and add it to the list
mCurrentDevice = new DeviceConfiguration(deviceName);
mDevices.add(mCurrentDevice);
} else if (LayoutConfigsXsd.NODE_DEFAULT.equals(localName)) {
// create a new default config
mDefaultConfig = mCurrentConfig = new FolderConfiguration();
} else if (LayoutConfigsXsd.NODE_CONFIG.equals(localName)) {
// create a new config
mCurrentConfig = new FolderConfiguration();
// init with default config if applicable
if (mDefaultConfig != null) {
mCurrentConfig.set(mDefaultConfig);
}
// get the name of the config
String deviceName = attributes.getValue("", LayoutConfigsXsd.ATTR_NAME);
// give it to the current device.
mCurrentDevice.addConfig(deviceName, mCurrentConfig);
} else if (LayoutConfigsXsd.NODE_SCREEN_DIMENSION.equals(localName)) {
mSize1 = mSize2 = null;
}
mStringAccumulator.setLength(0);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
mStringAccumulator.append(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
if (LayoutConfigsXsd.NODE_DEVICE.equals(localName)) {
mCurrentDevice = null;
mDefaultConfig = null;
} else if (LayoutConfigsXsd.NODE_CONFIG.equals(localName)) {
mCurrentConfig = null;
} else if (LayoutConfigsXsd.NODE_SCREEN_SIZE.equals(localName)) {
ScreenSizeQualifier ssq = new ScreenSizeQualifier(
ScreenSize.getEnum(mStringAccumulator.toString()));
mCurrentConfig.setScreenSizeQualifier(ssq);
} else if (LayoutConfigsXsd.NODE_SCREEN_RATIO.equals(localName)) {
ScreenRatioQualifier srq = new ScreenRatioQualifier(
ScreenRatio.getEnum(mStringAccumulator.toString()));
mCurrentConfig.setScreenRatioQualifier(srq);
} else if (LayoutConfigsXsd.NODE_SCREEN_ORIENTATION.equals(localName)) {
ScreenOrientationQualifier soq = new ScreenOrientationQualifier(
ScreenOrientation.getEnum(mStringAccumulator.toString()));
mCurrentConfig.setScreenOrientationQualifier(soq);
} else if (LayoutConfigsXsd.NODE_PIXEL_DENSITY.equals(localName)) {
PixelDensityQualifier pdq = new PixelDensityQualifier(
Density.getEnum(mStringAccumulator.toString()));
mCurrentConfig.setPixelDensityQualifier(pdq);
} else if (LayoutConfigsXsd.NODE_TOUCH_TYPE.equals(localName)) {
TouchScreenQualifier tsq = new TouchScreenQualifier(
TouchScreenType.getEnum(mStringAccumulator.toString()));
mCurrentConfig.setTouchTypeQualifier(tsq);
} else if (LayoutConfigsXsd.NODE_KEYBOARD_STATE.equals(localName)) {
KeyboardStateQualifier ksq = new KeyboardStateQualifier(
KeyboardState.getEnum(mStringAccumulator.toString()));
mCurrentConfig.setKeyboardStateQualifier(ksq);
} else if (LayoutConfigsXsd.NODE_TEXT_INPUT_METHOD.equals(localName)) {
TextInputMethodQualifier timq = new TextInputMethodQualifier(
TextInputMethod.getEnum(mStringAccumulator.toString()));
mCurrentConfig.setTextInputMethodQualifier(timq);
} else if (LayoutConfigsXsd.NODE_NAV_METHOD.equals(localName)) {
NavigationMethodQualifier nmq = new NavigationMethodQualifier(
NavigationMethod.getEnum(mStringAccumulator.toString()));
mCurrentConfig.setNavigationMethodQualifier(nmq);
} else if (LayoutConfigsXsd.NODE_SCREEN_DIMENSION.equals(localName)) {
ScreenDimensionQualifier qual = ScreenDimensionQualifier.getQualifier(mSize1, mSize2);
if (qual != null) {
mCurrentConfig.setScreenDimensionQualifier(qual);
}
} else if (LayoutConfigsXsd.NODE_SIZE.equals(localName)) {
if (mSize1 == null) {
mSize1 = mStringAccumulator.toString();
} else if (mSize2 == null) {
mSize2 = mStringAccumulator.toString();
}
}
}
}

View File

@@ -19,6 +19,24 @@ package com.android.ide.eclipse.adt.internal.sdk;
import com.android.ddmlib.IDevice;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.project.AndroidClasspathContainerInitializer;
import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenDimensionQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier;
import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier.KeyboardState;
import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier.NavigationMethod;
import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier.Density;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier.ScreenOrientation;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier.ScreenRatio;
import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier.ScreenSize;
import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier.TextInputMethod;
import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier.TouchScreenType;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceMonitor;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceMonitor.IProjectListener;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.LayoutBridge;
@@ -41,15 +59,31 @@ import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Validator;
/**
* Central point to load, manipulate and deal with the Android SDK. Only one SDK can be used
* at the same time.
@@ -73,6 +107,8 @@ public class Sdk implements IProjectListener {
new HashMap<IProject, ApkSettings>();
private final String mDocBaseUrl;
private List<DeviceConfiguration> mLayoutDevices = new ArrayList<DeviceConfiguration>();
/**
* Classes implementing this interface will receive notification when targets are changed.
*/
@@ -432,6 +468,9 @@ public class Sdk implements IProjectListener {
// pre-compute some paths
mDocBaseUrl = getDocumentationBaseUrl(mManager.getLocation() +
SdkConstants.OS_SDK_DOCS_FOLDER);
// create some built-in layout devices
createDefaultLayoutDevices();
}
/**
@@ -518,6 +557,173 @@ public class Sdk implements IProjectListener {
// ignore this. The project will be added to the map the first time the target needs
// to be resolved.
}
// ---------- Device Configuration methods ----------
/**
* A SAX error handler that captures the errors and warnings.
* This allows us to capture *all* errors and just not get an exception on the first one.
*/
private static class CaptureErrorHandler implements ErrorHandler {
private final String mSourceLocation;
private boolean mFoundError = false;
CaptureErrorHandler(String sourceLocation) {
mSourceLocation = sourceLocation;
}
public boolean foundError() {
return mFoundError;
}
/**
* @throws SAXException
*/
public void error(SAXParseException ex) throws SAXException {
mFoundError = true;
AdtPlugin.log(ex, "Error validating %1$s", mSourceLocation);
}
/**
* @throws SAXException
*/
public void fatalError(SAXParseException ex) throws SAXException {
mFoundError = true;
AdtPlugin.log(ex, "Error validating %1$s", mSourceLocation);
}
/**
* @throws SAXException
*/
public void warning(SAXParseException ex) throws SAXException {
// ignore those for now.
}
}
/**
* Returns the list of {@link DeviceConfiguration} found in the SDK.
*/
public List<DeviceConfiguration> getLayoutDevices() {
return mLayoutDevices;
}
/**
* Parses the SDK add-ons to look for files called {@link SdkConstants#FN_DEVICES_XML} to
* load {@link DeviceConfiguration} from them.
*/
public void parseAddOnLayoutDevices() {
SAXParserFactory parserFactory = SAXParserFactory.newInstance();
parserFactory.setNamespaceAware(true);
IAndroidTarget[] targets = mManager.getTargets();
for (IAndroidTarget target : targets) {
if (target.isPlatform() == false) {
File deviceXml = new File(target.getLocation(), SdkConstants.FN_DEVICES_XML);
if (deviceXml.isFile()) {
parseLayoutDevices(parserFactory, deviceXml);
}
}
}
mLayoutDevices = Collections.unmodifiableList(mLayoutDevices);
}
/**
* Does the actual parsing of a devices.xml file.
*/
private void parseLayoutDevices(SAXParserFactory parserFactory, File deviceXml) {
// first we validate the XML
try {
Source source = new StreamSource(new FileReader(deviceXml));
CaptureErrorHandler errorHandler = new CaptureErrorHandler(deviceXml.getAbsolutePath());
Validator validator = LayoutConfigsXsd.getValidator(errorHandler);
validator.validate(source);
if (errorHandler.foundError() == false) {
// do the actual parsing
LayoutDeviceHandler handler = new LayoutDeviceHandler();
SAXParser parser = parserFactory.newSAXParser();
parser.parse(new InputSource(new FileInputStream(deviceXml)), handler);
// get the parsed devices
mLayoutDevices.addAll(handler.getDevices());
}
} catch (SAXException e) {
AdtPlugin.log(e, "Error parsing %1$s", deviceXml.getAbsoluteFile());
} catch (FileNotFoundException e) {
// this shouldn't happen as we check above.
} catch (IOException e) {
AdtPlugin.log(e, "Error reading %1$s", deviceXml.getAbsoluteFile());
} catch (ParserConfigurationException e) {
AdtPlugin.log(e, "Error parsing %1$s", deviceXml.getAbsoluteFile());
}
}
/**
* Creates some built-it layout devices.
*/
private void createDefaultLayoutDevices() {
DeviceConfiguration adp1 = new DeviceConfiguration("ADP1");
mLayoutDevices.add(adp1);
// default config
FolderConfiguration defConfig = new FolderConfiguration();
defConfig.addQualifier(new ScreenSizeQualifier(ScreenSize.NORMAL));
defConfig.addQualifier(new ScreenRatioQualifier(ScreenRatio.NOTLONG));
defConfig.addQualifier(new PixelDensityQualifier(Density.MEDIUM));
defConfig.addQualifier(new TouchScreenQualifier(TouchScreenType.FINGER));
defConfig.addQualifier(new KeyboardStateQualifier(KeyboardState.SOFT));
defConfig.addQualifier(new TextInputMethodQualifier(TextInputMethod.QWERTY));
defConfig.addQualifier(new NavigationMethodQualifier(NavigationMethod.TRACKBALL));
defConfig.addQualifier(new ScreenDimensionQualifier(480, 320));
// specific configs
FolderConfiguration closedPort = new FolderConfiguration();
closedPort.set(defConfig);
closedPort.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.PORTRAIT));
adp1.addConfig("Portrait, closed", closedPort);
FolderConfiguration closedLand = new FolderConfiguration();
closedLand.set(defConfig);
closedLand.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
adp1.addConfig("Landscape, closed", closedLand);
FolderConfiguration opened = new FolderConfiguration();
opened.set(defConfig);
opened.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
opened.addQualifier(new KeyboardStateQualifier(KeyboardState.EXPOSED));
adp1.addConfig("Landscape, opened", opened);
DeviceConfiguration ion = new DeviceConfiguration("Ion");
mLayoutDevices.add(ion);
// default config
defConfig = new FolderConfiguration();
defConfig.addQualifier(new ScreenSizeQualifier(ScreenSize.NORMAL));
defConfig.addQualifier(new ScreenRatioQualifier(ScreenRatio.NOTLONG));
defConfig.addQualifier(new PixelDensityQualifier(Density.MEDIUM));
defConfig.addQualifier(new TouchScreenQualifier(TouchScreenType.FINGER));
defConfig.addQualifier(new KeyboardStateQualifier(KeyboardState.EXPOSED));
defConfig.addQualifier(new TextInputMethodQualifier(TextInputMethod.NOKEY));
defConfig.addQualifier(new NavigationMethodQualifier(NavigationMethod.TRACKBALL));
defConfig.addQualifier(new ScreenDimensionQualifier(480, 320));
// specific configs
FolderConfiguration landscape = new FolderConfiguration();
landscape.set(defConfig);
landscape.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
ion.addConfig("Landscape", landscape);
FolderConfiguration portrait = new FolderConfiguration();
portrait.set(defConfig);
portrait.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.PORTRAIT));
ion.addConfig("Portrait", portrait);
}
}

View File

@@ -92,7 +92,7 @@
<xsd:simpleType>
<xsd:restriction base="xsd:token">
<xsd:enumeration value="small" />
<xsd:enumeration value="medium" />
<xsd:enumeration value="normal" />
<xsd:enumeration value="large" />
</xsd:restriction>
</xsd:simpleType>