diff options
14 files changed, 353 insertions, 1171 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigEditDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigEditDialog.java deleted file mode 100644 index bd45400..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigEditDialog.java +++ /dev/null @@ -1,356 +0,0 @@ -/* - * 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.editors.layout.configuration; - -import com.android.ide.common.resources.configuration.FolderConfiguration; -import com.android.ide.common.resources.configuration.LanguageQualifier; -import com.android.ide.common.resources.configuration.NightModeQualifier; -import com.android.ide.common.resources.configuration.RegionQualifier; -import com.android.ide.common.resources.configuration.ResourceQualifier; -import com.android.ide.common.resources.configuration.UiModeQualifier; -import com.android.ide.common.resources.configuration.VersionQualifier; -import com.android.ide.eclipse.adt.internal.editors.IconFactory; -import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice; -import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector; -import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.ConfigurationState; -import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.IQualifierFilter; -import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.SelectorMode; -import com.android.sdkuilib.ui.GridDialog; - -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.VerifyEvent; -import org.eclipse.swt.events.VerifyListener; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; - -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.ParseException; -import java.util.regex.Pattern; - -/** - * Dialog to edit both a {@link LayoutDevice}, and a {@link FolderConfiguration} at the same time. - */ -public class ConfigEditDialog extends GridDialog { - - private static final Pattern FLOAT_PATTERN; - static { - // get the decimal separator char - DecimalFormatSymbols dfs = new DecimalFormatSymbols(); - - // make a pattern that's basically ##.# where .# is optional and where . can be . or , - // depending on the locale - FLOAT_PATTERN = Pattern.compile( - "\\d*(" + //$NON-NLS-1$ - Pattern.quote(new String(new char[] { dfs.getDecimalSeparator() })) + - "\\d?)?"); //$NON-NLS-1$ - } - - private final FolderConfiguration mConfig = new FolderConfiguration(); - - private ConfigurationSelector mConfigSelector; - private Composite mStatusComposite; - private Label mStatusLabel; - private Label mStatusImage; - - private Image mError; - - private String mDeviceName; - private String mConfigName; - private float mXDpi = Float.NaN; - private float mYDpi = Float.NaN; - - private final DecimalFormat mDecimalFormat = new DecimalFormat(); - - - public ConfigEditDialog(Shell parentShell, FolderConfiguration config) { - super(parentShell, 1, false); - mConfig.set(config); - } - - public void setDeviceName(String name) { - mDeviceName = name; - } - - public String getDeviceName() { - return mDeviceName; - } - - public void setXDpi(float xdpi) { - mXDpi = xdpi; - } - - public float getXDpi() { - return mXDpi; - } - - public void setYDpi(float ydpi) { - mYDpi = ydpi; - } - - public float getYDpi() { - return mYDpi; - } - - public void setConfigName(String name) { - mConfigName = name; - } - - public String getConfigName() { - return mConfigName; - } - - public void setConfig(FolderConfiguration config) { - mConfig.set(config); - } - - public void getConfig(FolderConfiguration config) { - config.set(mConfig); - config.updateScreenWidthAndHeight(); - } - - @Override - public void createDialogContent(Composite parent) { - mError = IconFactory.getInstance().getIcon("error"); //$NON-NLS-1$ - - Group deviceGroup = new Group(parent, SWT.NONE); - deviceGroup.setText("Device"); - deviceGroup.setLayoutData(new GridData(GridData.FILL_BOTH)); - deviceGroup.setLayout(new GridLayout(2, false)); - - Label l = new Label(deviceGroup, SWT.None); - l.setText("Name"); - - final Text deviceNameText = new Text(deviceGroup, SWT.BORDER); - deviceNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - if (mDeviceName != null) { - deviceNameText.setText(mDeviceName); - } - deviceNameText.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - mDeviceName = deviceNameText.getText().trim(); - validateOk(); - } - }); - - - VerifyListener floatVerifier = new VerifyListener() { - @Override - public void verifyText(VerifyEvent event) { - // combine the current content and the new text - String text = ((Text)event.widget).getText(); - text = text.substring(0, event.start) + event.text + text.substring(event.end); - - // now make sure it's a match for the regex - event.doit = FLOAT_PATTERN.matcher(text).matches(); - } - }; - - l = new Label(deviceGroup, SWT.None); - l.setText("x dpi"); - - final Text deviceXDpiText = new Text(deviceGroup, SWT.BORDER); - deviceXDpiText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - if (Float.isNaN(mXDpi) == false) { - deviceXDpiText.setText(String.format("%.1f", mXDpi)); //$NON-NLS-1$ - } - deviceXDpiText.addVerifyListener(floatVerifier); - deviceXDpiText.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - String value = deviceXDpiText.getText(); - if (value.length() == 0) { - mXDpi = Float.NaN; - } else { - try { - mXDpi = mDecimalFormat.parse(value).floatValue(); - } catch (ParseException exception) { - mXDpi = Float.NaN; - } - } - } - }); - - l = new Label(deviceGroup, SWT.None); - l.setText("y dpi"); - - final Text deviceYDpiText = new Text(deviceGroup, SWT.BORDER); - deviceYDpiText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - if (Float.isNaN(mYDpi) == false) { - deviceYDpiText.setText(String.format("%.1f", mYDpi)); //$NON-NLS-1$ - } - deviceYDpiText.addVerifyListener(floatVerifier); - deviceYDpiText.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - String value = deviceYDpiText.getText(); - if (value.length() == 0) { - mYDpi = Float.NaN; - } else { - try { - mYDpi = mDecimalFormat.parse(value).floatValue(); - } catch (ParseException exception) { - mYDpi = Float.NaN; - } - } - } - }); - - Group configGroup = new Group(parent, SWT.NONE); - configGroup.setText("Configuration"); - configGroup.setLayoutData(new GridData(GridData.FILL_BOTH)); - configGroup.setLayout(new GridLayout(2, false)); - - l = new Label(configGroup, SWT.None); - l.setText("Name"); - - final Text configNameText = new Text(configGroup, SWT.BORDER); - configNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - if (mConfigName != null) { - configNameText.setText(mConfigName); - } - configNameText.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - mConfigName = configNameText.getText().trim(); - validateOk(); - } - }); - - mConfigSelector = new ConfigurationSelector(configGroup, SelectorMode.DEVICE_ONLY); - // configure the selector to be in "device mode" and not accept language/region/version - // since those are selected from a different combo - // FIXME: add version combo. - mConfigSelector.setQualifierFilter(new IQualifierFilter() { - @Override - public boolean accept(ResourceQualifier qualifier) { - if (qualifier instanceof LanguageQualifier || - qualifier instanceof RegionQualifier || - qualifier instanceof UiModeQualifier || - qualifier instanceof NightModeQualifier || - qualifier instanceof VersionQualifier) { - return false; - } - - return true; - } - }); - mConfigSelector.setConfiguration(mConfig); - GridData gd; - mConfigSelector.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 2; - gd.widthHint = ConfigurationSelector.WIDTH_HINT; - gd.heightHint = ConfigurationSelector.HEIGHT_HINT; - - // add a listener to check on the validity of the FolderConfiguration as - // they are built. - mConfigSelector.setOnChangeListener(new Runnable() { - @Override - public void run() { - if (mConfigSelector.getState() == ConfigurationState.OK) { - mConfigSelector.getConfiguration(mConfig); - } - - validateOk(); - } - }); - - mStatusComposite = new Composite(parent, SWT.NONE); - mStatusComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - GridLayout gl = new GridLayout(2, false); - mStatusComposite.setLayout(gl); - gl.marginHeight = gl.marginWidth = 0; - - mStatusImage = new Label(mStatusComposite, SWT.NONE); - mStatusLabel = new Label(mStatusComposite, SWT.NONE); - mStatusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - resetStatus(); - } - - @Override - protected Control createContents(Composite parent) { - Control c = super.createContents(parent); - validateOk(); - return c; - } - - /** - * resets the status label to show the file that will be created. - */ - private void resetStatus() { - String displayString = Dialog.shortenText( - String.format("Config: %1$s", mConfig.toString()), - mStatusLabel); - mStatusLabel.setText(displayString); - } - - private void setError(String text) { - String displayString = Dialog.shortenText(text, mStatusLabel); - mStatusLabel.setText(displayString); - mStatusImage.setImage(mError); - getButton(IDialogConstants.OK_ID).setEnabled(false); - } - - private void validateOk() { - // check the device name - if (mDeviceName == null || mDeviceName.length() == 0) { - setError("Device name must not be empty"); - return; - } - - // check the config name - if (mConfigName == null || mConfigName.length() == 0) { - setError("Configuration name must not be empty"); - return; - } - - // and check the config itself - ConfigurationState state = mConfigSelector.getState(); - - switch (state) { - case INVALID_CONFIG: - ResourceQualifier invalidQualifier = mConfigSelector.getInvalidQualifier(); - setError(String.format( - "Invalid Configuration: %1$s has no filter set.", - invalidQualifier.getName())); - return; - case REGION_WITHOUT_LANGUAGE: - setError("The Region qualifier requires the Language qualifier."); - return; - } - - // no error - mStatusImage.setImage(null); - resetStatus(); - getButton(IDialogConstants.OK_ID).setEnabled(true); - - // need to relayout, because of the change in size in mErrorImage. - mStatusComposite.layout(); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigManagerDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigManagerDialog.java deleted file mode 100644 index 2adefa7..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigManagerDialog.java +++ /dev/null @@ -1,566 +0,0 @@ -/* - * 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.editors.layout.configuration; - -import com.android.ddmuilib.TableHelper; -import com.android.ide.common.resources.configuration.FolderConfiguration; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice; -import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice.DeviceConfig; -import com.android.ide.eclipse.adt.internal.sdk.LayoutDeviceManager; -import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.sdkuilib.ui.GridDialog; - -import org.eclipse.jface.dialogs.IDialogConstants; -import org.eclipse.jface.viewers.ILabelProviderListener; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.ITableLabelProvider; -import org.eclipse.jface.viewers.ITreeContentProvider; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.TreePath; -import org.eclipse.jface.viewers.TreeSelection; -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.window.Window; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Tree; - -import java.util.List; - -/** - * Dialog to view the layout devices with action button to create/edit/delete/copy layout devices - * and configs. - * - */ -public class ConfigManagerDialog extends GridDialog { - - private final static String COL_NAME = AdtPlugin.PLUGIN_ID + ".configmanager.name"; //$NON-NLS-1$ - private final static String COL_CONFIG = AdtPlugin.PLUGIN_ID + ".configmanager.config"; //$NON-NLS-1$ - - /** - * enum to represent the different origin of the layout devices. - */ - private static enum DeviceType { - DEFAULT("Default"), - ADDON("Add-on"), - CUSTOM("Custom"); - - private final String mDisplay; - - DeviceType(String display) { - mDisplay = display; - } - - String getDisplayString() { - return mDisplay; - } - } - - /** - * simple class representing the tree selection with the proper types. - */ - private static class DeviceSelection { - public DeviceSelection(DeviceType type, LayoutDevice device, - DeviceConfig config) { - this.type = type; - this.device = device; - this.config = config; - } - - final DeviceType type; - final LayoutDevice device; - final DeviceConfig config; - } - - private final LayoutDeviceManager mManager; - - private TreeViewer mTreeViewer; - private Button mNewButton; - private Button mEditButton; - private Button mCopyButton; - private Button mDeleteButton; - - /** - * Content provider of the {@link TreeViewer}. The expected input is - * {@link LayoutDeviceManager}. - * - */ - private final static class DeviceContentProvider implements ITreeContentProvider { - private final static DeviceType[] sCategory = new DeviceType[] { - DeviceType.DEFAULT, DeviceType.ADDON, DeviceType.CUSTOM - }; - - private LayoutDeviceManager mLayoutDeviceManager; - - public DeviceContentProvider() { - } - - @Override - public Object[] getElements(Object inputElement) { - return sCategory; - } - - @Override - public Object[] getChildren(Object parentElement) { - if (parentElement instanceof DeviceType) { - if (DeviceType.DEFAULT.equals(parentElement)) { - return mLayoutDeviceManager.getDefaultLayoutDevices().toArray(); - } else if (DeviceType.ADDON.equals(parentElement)) { - return mLayoutDeviceManager.getAddOnLayoutDevice().toArray(); - } else if (DeviceType.CUSTOM.equals(parentElement)) { - return mLayoutDeviceManager.getUserLayoutDevices().toArray(); - } - } else if (parentElement instanceof LayoutDevice) { - LayoutDevice device = (LayoutDevice)parentElement; - return device.getConfigs().toArray(); - } - - return null; - } - - @Override - public Object getParent(Object element) { - // parent cannot be computed. this is fine. - return null; - } - - @Override - public boolean hasChildren(Object element) { - if (element instanceof DeviceType) { - if (DeviceType.DEFAULT.equals(element)) { - return mLayoutDeviceManager.getDefaultLayoutDevices().size() > 0; - } else if (DeviceType.ADDON.equals(element)) { - return mLayoutDeviceManager.getAddOnLayoutDevice().size() > 0; - } else if (DeviceType.CUSTOM.equals(element)) { - return mLayoutDeviceManager.getUserLayoutDevices().size() > 0; - } - } else if (element instanceof LayoutDevice) { - LayoutDevice device = (LayoutDevice)element; - return device.getConfigs().size() > 0; - } - - return false; - } - - - @Override - public void dispose() { - // nothing to dispose - } - - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - if (newInput instanceof LayoutDeviceManager) { - mLayoutDeviceManager = (LayoutDeviceManager)newInput; - return; - } - - // when the dialog closes we get null input - if (newInput != null) { - throw new IllegalArgumentException( - "ConfigContentProvider requires input to be LayoutDeviceManager"); - } - } - } - - /** - * Label provider for the {@link TreeViewer}. - * Supported elements are {@link DeviceType}, {@link LayoutDevice}, and {@link DeviceConfig}. - * - */ - private final static class DeviceLabelProvider implements ITableLabelProvider { - - @Override - public String getColumnText(Object element, int columnIndex) { - if (element instanceof DeviceType) { - if (columnIndex == 0) { - return ((DeviceType)element).getDisplayString(); - } - } else if (element instanceof LayoutDevice) { - if (columnIndex == 0) { - return ((LayoutDevice)element).getName(); - } - } else if (element instanceof DeviceConfig) { - if (columnIndex == 0) { - return ((DeviceConfig)element).getName(); - } else { - return ((DeviceConfig)element).getConfig().toString(); - } - } - return null; - } - - @Override - public Image getColumnImage(Object element, int columnIndex) { - // no image - return null; - } - - @Override - public void addListener(ILabelProviderListener listener) { - // no listener - } - - @Override - public void removeListener(ILabelProviderListener listener) { - // no listener - } - - @Override - public void dispose() { - // nothing to dispose - } - - @Override - public boolean isLabelProperty(Object element, String property) { - return false; - } - } - - protected ConfigManagerDialog(Shell parentShell) { - super(parentShell, 2, false); - mManager = Sdk.getCurrent().getLayoutDeviceManager(); - } - - @Override - protected int getShellStyle() { - return super.getShellStyle() | SWT.RESIZE; - } - - @Override - protected void configureShell(Shell newShell) { - super.configureShell(newShell); - newShell.setText("Device Configurations"); - } - - @Override - public void createDialogContent(final Composite parent) { - GridData gd; - GridLayout gl; - - Tree tree = new Tree(parent, SWT.SINGLE | SWT.FULL_SELECTION); - tree.setLayoutData(gd = new GridData(GridData.FILL_BOTH)); - gd.widthHint = 700; - - tree.setHeaderVisible(true); - tree.setLinesVisible(true); - TableHelper.createTreeColumn(tree, "Name", SWT.LEFT, 150, COL_NAME, - AdtPlugin.getDefault().getPreferenceStore()); - TableHelper.createTreeColumn(tree, "Configuration", SWT.LEFT, 500, COL_CONFIG, - AdtPlugin.getDefault().getPreferenceStore()); - - mTreeViewer = new TreeViewer(tree); - mTreeViewer.setContentProvider(new DeviceContentProvider()); - mTreeViewer.setLabelProvider(new DeviceLabelProvider()); - mTreeViewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS); - mTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { - @Override - public void selectionChanged(SelectionChangedEvent event) { - setEnabled(getSelection()); - } - }); - - Composite buttons = new Composite(parent, SWT.NONE); - buttons.setLayoutData(new GridData(GridData.FILL_VERTICAL)); - buttons.setLayout(gl = new GridLayout()); - gl.marginHeight = gl.marginWidth = 0; - - mNewButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mNewButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mNewButton.setText("New..."); - mNewButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - DeviceSelection selection = getSelection(); - - ConfigEditDialog dlg = new ConfigEditDialog(parent.getShell(), null); - if (selection.device != null) { - dlg.setDeviceName(selection.device.getName()); - dlg.setXDpi(selection.device.getXDpi()); - dlg.setYDpi(selection.device.getYDpi()); - } - if (selection.config != null) { - dlg.setConfigName(selection.config.getName()); - dlg.setConfig(selection.config.getConfig()); - } - - if (dlg.open() == Window.OK) { - String deviceName = dlg.getDeviceName(); - String configName = dlg.getConfigName(); - FolderConfiguration config = new FolderConfiguration(); - dlg.getConfig(config); - - // first if there was no original device, we create one. - // Because the new button is disabled when something else than "custom" is - // selected, we always add to the user devices without checking. - LayoutDevice d; - if (selection.device == null) { - // FIXME: this doesn't check if the device name is taken. - d = mManager.addUserDevice(deviceName, dlg.getXDpi(), dlg.getYDpi()); - } else { - // search for it. - d = mManager.getUserLayoutDevice(deviceName); - } - - if (d != null) { - // then if there was no config, we add it, otherwise we edit it - // (same method that adds/replace a config). - // FIXME this doesn't check if the name was already taken. - mManager.addUserConfiguration(d, configName, config); - - mTreeViewer.refresh(); - select(d, configName); - } - } - } - }); - - mEditButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mEditButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mEditButton.setText("Edit..."); - mEditButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - DeviceSelection selection = getSelection(); - ConfigEditDialog dlg = new ConfigEditDialog(parent.getShell(), null); - dlg.setDeviceName(selection.device.getName()); - dlg.setXDpi(selection.device.getXDpi()); - dlg.setYDpi(selection.device.getYDpi()); - dlg.setConfigName(selection.config.getName()); - dlg.setConfig(selection.config.getConfig()); - - if (dlg.open() == Window.OK) { - String deviceName = dlg.getDeviceName(); - String configName = dlg.getConfigName(); - FolderConfiguration config = new FolderConfiguration(); - dlg.getConfig(config); - - // replace the device if needed. - // FIXME: this doesn't check if the replacement name doesn't exist already. - LayoutDevice d = mManager.replaceUserDevice(selection.device, deviceName, - dlg.getXDpi(), dlg.getYDpi()); - - // and add/replace the config - mManager.replaceUserConfiguration(d, selection.config.getName(), configName, - config); - - mTreeViewer.refresh(); - select(d, configName); - } - } - }); - - mCopyButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mCopyButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mCopyButton.setText("Copy"); - mCopyButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - DeviceSelection selection = getSelection(); - - // is the source a default/add-on device, or are we copying a full device? - // if so the target device is a new device. - LayoutDevice targetDevice = selection.device; - if (selection.type == DeviceType.DEFAULT || selection.type == DeviceType.ADDON || - selection.config == null) { - // create a new device - targetDevice = mManager.addUserDevice( - selection.device.getName() + " Copy", // new name - selection.device.getXDpi(), - selection.device.getYDpi()); - } - - String newConfigName = null; // name of the single new config. used for the select. - - // are we copying the full device? - if (selection.config == null) { - // get the config from the origin device - List<DeviceConfig> configs = selection.device.getConfigs(); - - // and copy them in the target device - for (DeviceConfig config : configs) { - // we need to make a copy of the config object, or it could be modified - // in default/addon by editing the version in the new device. - FolderConfiguration copy = new FolderConfiguration(); - copy.set(config.getConfig()); - - // the name can stay the same since we are copying a full device - // and the target device has its own new name. - mManager.addUserConfiguration(targetDevice, config.getName(), copy); - } - } else { - // only copy the config. target device is not the same as the selection, don't - // change the config name as we already changed the name of the device. - newConfigName = (selection.device != targetDevice) ? - selection.config.getName() : selection.config.getName() + " Copy"; - - // copy of the config - FolderConfiguration copy = new FolderConfiguration(); - copy.set(selection.config.getConfig()); - - // and create the config - mManager.addUserConfiguration(targetDevice, newConfigName, copy); - } - - mTreeViewer.refresh(); - - select(targetDevice, newConfigName); - } - }); - - mDeleteButton = new Button(buttons, SWT.PUSH | SWT.FLAT); - mDeleteButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - mDeleteButton.setText("Delete"); - mDeleteButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - DeviceSelection selection = getSelection(); - - if (selection.config != null) { - mManager.removeUserConfiguration(selection.device, selection.config.getName()); - } else if (selection.device != null) { - mManager.removeUserDevice(selection.device); - } - - mTreeViewer.refresh(); - - // either select the device (if we removed a entry, or the top custom node if - // we removed a device) - select(selection.config != null ? selection.device : null, null); - } - }); - - Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); - separator.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); - gd.horizontalSpan = 2; - - mTreeViewer.setInput(mManager); - setEnabled(null); // no selection at the start - } - - @Override - protected void createButtonsForButtonBar(Composite parent) { - // we only want an OK button. - createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); - } - - /** - * Returns a {@link DeviceSelection} object representing the selected path in the - * {@link TreeViewer} - */ - private DeviceSelection getSelection() { - // get the selection paths - TreeSelection selection = (TreeSelection)mTreeViewer.getSelection(); - TreePath[] paths =selection.getPaths(); - - if (paths.length == 0) { - return null; - } - - TreePath pathSelection = paths[0]; - - DeviceType type = (DeviceType)pathSelection.getFirstSegment(); - LayoutDevice device = null; - DeviceConfig config = null; - switch (pathSelection.getSegmentCount()) { - case 2: // layout device is selected - device = (LayoutDevice)pathSelection.getLastSegment(); - break; - case 3: // config is selected - device = (LayoutDevice)pathSelection.getSegment(1); - config = (DeviceConfig)pathSelection.getLastSegment(); - } - - return new DeviceSelection(type, device, config); - } - - /** - * Enables/disables the action button based on the {@link DeviceSelection}. - * @param selection the selection - */ - protected void setEnabled(DeviceSelection selection) { - if (selection == null) { - mNewButton.setEnabled(false); - mEditButton.setEnabled(false); - mCopyButton.setEnabled(false); - mDeleteButton.setEnabled(false); - } else { - switch (selection.type) { - case DEFAULT: - case ADDON: - // only allow copy if device is not null - mNewButton.setEnabled(false); - mEditButton.setEnabled(false); - mDeleteButton.setEnabled(false); - mCopyButton.setEnabled(selection.device != null); - break; - case CUSTOM: - mNewButton.setEnabled(true); // always true to create new devices. - mEditButton.setEnabled(selection.config != null); // only edit config for now - - boolean enabled = selection.device != null; // need at least selected device - mDeleteButton.setEnabled(enabled); // for delete and copy buttons - mCopyButton.setEnabled(enabled); - break; - } - } - } - - /** - * Selects a device and optionally a config. Because this is meant to show newly created/edited - * device/config, it'll only do so for {@link DeviceType#CUSTOM} devices. - * @param device the device to select - * @param configName the config to select (optional) - */ - private void select(LayoutDevice device, String configName) { - Object[] path; - if (device == null) { - // select the "custom" node - path = new Object[] { DeviceType.CUSTOM }; - } else if (configName == null) { - // this is the easy case. no config to select - path = new Object[] { DeviceType.CUSTOM, device }; - } else { - // this is more complex. we have the configName, but the tree contains DeviceConfig - // Look for the entry. - DeviceConfig match = null; - for (DeviceConfig config : device.getConfigs()) { - if (config.getName().equals(configName)) { - match = config; - break; - } - } - - if (match != null) { - path = new Object[] { DeviceType.CUSTOM, device, match }; - } else { - path = new Object[] { DeviceType.CUSTOM, device }; - } - } - - mTreeViewer.setSelection(new TreeSelection(new TreePath(path)), true /*reveal*/); - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java index 2e1434f..b4e052f 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java @@ -33,6 +33,7 @@ import com.android.ide.common.resources.ResourceFile; import com.android.ide.common.resources.ResourceFolder; import com.android.ide.common.resources.ResourceRepository; import com.android.ide.common.resources.configuration.DensityQualifier; +import com.android.ide.common.resources.configuration.DeviceConfigHelper; import com.android.ide.common.resources.configuration.FolderConfiguration; import com.android.ide.common.resources.configuration.LanguageQualifier; import com.android.ide.common.resources.configuration.NightModeQualifier; @@ -53,9 +54,6 @@ import com.android.ide.eclipse.adt.internal.resources.ResourceHelper; import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources; import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; -import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice; -import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice.DeviceConfig; -import com.android.ide.eclipse.adt.internal.sdk.LayoutDeviceManager; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.resources.Density; import com.android.resources.NightMode; @@ -66,6 +64,10 @@ import com.android.resources.ScreenSize; import com.android.resources.UiMode; import com.android.sdklib.AndroidVersion; import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.devices.Device; +import com.android.sdklib.devices.State; +import com.android.sdklib.internal.avd.AvdInfo; +import com.android.sdklib.internal.avd.AvdManager; import com.android.sdklib.repository.PkgProps; import com.android.sdklib.util.SparseIntArray; import com.android.util.Pair; @@ -118,6 +120,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.SortedSet; +import java.util.TreeMap; /** * A composite that displays the current configuration displayed in a Graphical Layout Editor. @@ -189,7 +192,7 @@ public class ConfigurationComposite extends Composite implements SelectionListen /** updates are disabled if > 0 */ private int mDisableUpdates = 0; - private List<LayoutDevice> mDeviceList; + private List<Device> mDeviceList = new ArrayList<Device>(); private final List<IAndroidTarget> mTargetList = new ArrayList<IAndroidTarget>(); private final List<String> mThemeList = new ArrayList<String>(); @@ -284,8 +287,8 @@ public class ConfigurationComposite extends Composite implements SelectionListen * rendering to its original configuration. */ private class ConfigState { - LayoutDevice device; - String configName; + Device device; + String stateName; ResourceQualifier[] locale; String theme; // TODO: Need to know if it's the project theme or the framework theme! @@ -302,14 +305,14 @@ public class ConfigurationComposite extends Composite implements SelectionListen if (device != null) { sb.append(device.getName()); sb.append(SEP); - if (configName == null) { - DeviceConfig config = getSelectedDeviceConfig(); - if (config != null) { - configName = config.getName(); + if (stateName == null) { + State state= getSelectedDeviceState(); + if (state != null) { + stateName = state.getName(); } } - if (configName != null) { - sb.append(configName); + if (stateName != null) { + sb.append(stateName); } sb.append(SEP); if (isLocaleSpecificLayout() && locale != null) { @@ -357,17 +360,17 @@ public class ConfigurationComposite extends Composite implements SelectionListen boolean setData(String data) { String[] values = data.split(SEP); if (values.length >= 6 && values.length <= 8) { - for (LayoutDevice d : mDeviceList) { + for (Device d : mDeviceList) { if (d.getName().equals(values[0])) { device = d; FolderConfiguration config = null; if (!values[1].isEmpty() && !values[1].equals("null")) { //$NON-NLS-1$ - configName = values[1]; - config = device.getFolderConfigByName(configName); - } else if (device.getConfigs().size() > 0) { - DeviceConfig first = device.getConfigs().get(0); - configName = first.getName(); - config = first.getConfig(); + stateName = values[1]; + config = DeviceConfigHelper.getFolderConfig(device, stateName); + } else if (device.getAllStates().size() > 0) { + State first = device.getAllStates().get(0); + stateName = first.getName(); + config = DeviceConfigHelper.getFolderConfig(first); } if (config != null) { // Load locale. Note that this can get overwritten by the @@ -507,7 +510,7 @@ public class ConfigurationComposite extends Composite implements SelectionListen mOrientationCombo = new ToolItem(toolBar, SWT.DROP_DOWN); mOrientationCombo.setImage(icons.getIcon(ICON_PORTRAIT)); - mOrientationCombo.setToolTipText("Flip Orientation"); + mOrientationCombo.setToolTipText("Go to next state"); @SuppressWarnings("unused") ToolItem separator4 = new ToolItem(toolBar, SWT.SEPARATOR); @@ -752,7 +755,7 @@ public class ConfigurationComposite extends Composite implements SelectionListen if (loadedConfigData) { // first make sure we have the config to adapt selectDevice(mState.device); - selectConfig(mState.configName); + selectState(mState.stateName); adaptConfigSelection(false /*needBestMatch*/); @@ -1145,12 +1148,12 @@ public class ConfigurationComposite extends Composite implements SelectionListen private static class ConfigMatch { final FolderConfiguration testConfig; - final LayoutDevice device; + final Device device; final String name; final ConfigBundle bundle; - public ConfigMatch(FolderConfiguration testConfig, - LayoutDevice device, String name, ConfigBundle bundle) { + public ConfigMatch(FolderConfiguration testConfig, Device device, String name, + ConfigBundle bundle) { this.testConfig = testConfig; this.device = device; this.name = name; @@ -1171,10 +1174,11 @@ public class ConfigurationComposite extends Composite implements SelectionListen * the current config. This must only be true if the current config is compatible. */ private void findAndSetCompatibleConfig(boolean favorCurrentConfig) { - // list of compatible device/config/locale + // list of compatible device/state/locale List<ConfigMatch> anyMatches = new ArrayList<ConfigMatch>(); - // list of actual best match (ie the file is a best match for the device/config) + // list of actual best match (ie the file is a best match for the + // device/state) List<ConfigMatch> bestMatches = new ArrayList<ConfigMatch>(); // get a locale that match the host locale roughly (may not be exact match on the region.) @@ -1219,27 +1223,30 @@ public class ConfigurationComposite extends Composite implements SelectionListen addRenderTargetToBundles(configBundles); - for (LayoutDevice device : mDeviceList) { - for (DeviceConfig config : device.getConfigs()) { + for (Device device : mDeviceList) { + for (State state : device.getAllStates()) { - // loop on the list of config bundles to create full configurations. + // loop on the list of config bundles to create full + // configurations. + FolderConfiguration stateConfig = DeviceConfigHelper.getFolderConfig(state); for (ConfigBundle bundle : configBundles) { // create a new config with device config FolderConfiguration testConfig = new FolderConfiguration(); - testConfig.set(config.getConfig()); + testConfig.set(stateConfig); // add on top of it, the extra qualifiers from the bundle testConfig.add(bundle.config); if (mEditedConfig.isMatchFor(testConfig)) { - // this is a basic match. record it in case we don't find a match + // this is a basic match. record it in case we don't + // find a match // where the edited file is a best config. - anyMatches.add(new ConfigMatch(testConfig, device, config.getName(), - bundle)); + anyMatches + .add(new ConfigMatch(testConfig, device, state.getName(), bundle)); if (isCurrentFileBestMatchFor(testConfig)) { // this is what we want. - bestMatches.add(new ConfigMatch(testConfig, device, config.getName(), + bestMatches.add(new ConfigMatch(testConfig, device, state.getName(), bundle)); } } @@ -1267,7 +1274,7 @@ public class ConfigurationComposite extends Composite implements SelectionListen // select the best device anyway. ConfigMatch match = selectConfigMatch(anyMatches); selectDevice(mState.device = match.device); - selectConfig(match.name); + selectState(match.name); selectLocale(mLocaleList.get(match.bundle.localeIndex)); mState.uiMode = UiMode.getByIndex(match.bundle.dockModeIndex); @@ -1285,13 +1292,13 @@ public class ConfigurationComposite extends Composite implements SelectionListen } else { // TODO: there is no device/config able to display the layout, create one. - // For the base config values, we'll take the first device and config, + // For the base config values, we'll take the first device and state, // and replace whatever qualifier required by the layout file. } } else { ConfigMatch match = selectConfigMatch(bestMatches); selectDevice(mState.device = match.device); - selectConfig(match.name); + selectState(match.name); selectLocale(mLocaleList.get(match.bundle.localeIndex)); mState.uiMode = UiMode.getByIndex(match.bundle.dockModeIndex); mState.night = NightMode.getByIndex(match.bundle.nightModeIndex); @@ -1493,10 +1500,9 @@ public class ConfigurationComposite extends Composite implements SelectionListen // check the device config (ie sans locale) boolean needConfigChange = true; // if still true, we need to find another config. boolean currentConfigIsCompatible = false; - DeviceConfig selectedConfig = getSelectedDeviceConfig(); - if (selectedConfig != null) { - String configName = selectedConfig.getName(); - FolderConfiguration currentConfig = mState.device.getFolderConfigByName(configName); + State selectedState = getSelectedDeviceState(); + if (selectedState != null) { + FolderConfiguration currentConfig = DeviceConfigHelper.getFolderConfig(selectedState); if (currentConfig != null && mEditedConfig.isMatchFor(currentConfig)) { currentConfigIsCompatible = true; // current config is compatible if (needBestMatch == false || isCurrentFileBestMatchFor(currentConfig)) { @@ -1506,15 +1512,15 @@ public class ConfigurationComposite extends Composite implements SelectionListen } if (needConfigChange) { - // if the current config/locale isn't a correct match, then - // look for another config/locale in the same device. + // if the current state/locale isn't a correct match, then + // look for another state/locale in the same device. FolderConfiguration testConfig = new FolderConfiguration(); // first look in the current device. String matchName = null; int localeIndex = -1; - mainloop: for (DeviceConfig config : mState.device.getConfigs()) { - testConfig.set(config.getConfig()); + mainloop: for (State state : mState.device.getAllStates()) { + testConfig.set(DeviceConfigHelper.getFolderConfig(state)); // loop on the locales. for (int i = 0 ; i < mLocaleList.size() ; i++) { @@ -1526,7 +1532,7 @@ public class ConfigurationComposite extends Composite implements SelectionListen if (mEditedConfig.isMatchFor(testConfig) && isCurrentFileBestMatchFor(testConfig)) { - matchName = config.getName(); + matchName = state.getName(); localeIndex = i; break mainloop; } @@ -1534,11 +1540,12 @@ public class ConfigurationComposite extends Composite implements SelectionListen } if (matchName != null) { - selectConfig(matchName); + selectState(matchName); selectLocale(mLocaleList.get(localeIndex)); } else { - // no match in current device with any config/locale - // attempt to find another device that can display this particular config. + // no match in current device with any state/locale + // attempt to find another device that can display this + // particular state. findAndSetCompatibleConfig(currentConfigIsCompatible); } } @@ -1590,9 +1597,9 @@ public class ConfigurationComposite extends Composite implements SelectionListen private void saveState() { if (mDisableUpdates == 0) { - DeviceConfig deviceConfig = getSelectedDeviceConfig(); - String configName = deviceConfig != null ? deviceConfig.getName() : null; - mState.configName = configName; + State state = getSelectedDeviceState(); + String stateName = state != null ? state.getName() : null; + mState.stateName = stateName; // since the locales are relative to the project, only keeping the index is enough mState.locale = getSelectedLocale(); @@ -1721,7 +1728,10 @@ public class ConfigurationComposite extends Composite implements SelectionListen } } - private String getDeviceLabel(LayoutDevice device, boolean brief) { + private String getDeviceLabel(Device device, boolean brief) { + if(device == null) { + return ""; + } String name = device.getName(); if (brief) { @@ -1747,40 +1757,71 @@ public class ConfigurationComposite extends Composite implements SelectionListen Listener menuListener = new Listener() { @Override public void handleEvent(Event event) { + Device current = getSelectedDevice(); Menu menu = new Menu(ConfigurationComposite.this.getShell(), SWT.POP_UP); - LayoutDevice current = getSelectedDevice(); - if (mDeviceList != null && mDeviceList.size() > 0) { - for (final LayoutDevice device : mDeviceList) { - String title = getDeviceLabel(device, false); - MenuItem item = new MenuItem(menu, SWT.CHECK); - item.setText(title); + AvdManager avdManager = Sdk.getCurrent().getAvdManager(); + AvdInfo[] avds = avdManager.getValidAvds(); + boolean separatorNeeded = false; + for (AvdInfo avd : avds) { + for (final Device d : mDeviceList) { + if (d.getManufacturer().equals(avd.getDeviceManufacturer()) + && d.getName().equals(avd.getDeviceName())) { + separatorNeeded = true; + MenuItem item = new MenuItem(menu, SWT.CHECK); + item.setText(avd.getName()); + item.setSelection(current == d); - boolean selected = current == device; - if (selected) { - item.setSelection(true); - } + item.addSelectionListener(new SelectionAdapter() { - item.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - selectDevice(device); - onDeviceChange(true /*recomputeLayout*/); - } - }); + @Override + public void widgetSelected(SelectionEvent e) { + selectDevice(d); + onDeviceChange(true /*recomputeLayout*/); + } + }); + } } + } + if (separatorNeeded) { @SuppressWarnings("unused") MenuItem separator = new MenuItem(menu, SWT.SEPARATOR); + } - MenuItem item = new MenuItem(menu, SWT.PUSH); - item.setText("Add Custom..."); - item.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onCustomDeviceConfig(); + // Group the devices by manufacturer, then put them in the menu + if (!mDeviceList.isEmpty()) { + Map<String, List<Device>> manufacturers = new TreeMap<String, List<Device>>(); + for (Device device : mDeviceList) { + List<Device> devices; + if(manufacturers.containsKey(device.getManufacturer())) { + devices = manufacturers.get(device.getManufacturer()); + } else { + devices = new ArrayList<Device>(); + manufacturers.put(device.getManufacturer(), devices); } - }); + devices.add(device); + } + for (List<Device> devices : manufacturers.values()) { + MenuItem item = new MenuItem(menu, SWT.CASCADE); + item.setText(devices.get(0).getManufacturer()); + Menu manufacturerMenu = new Menu(menu); + item.setMenu(manufacturerMenu); + for (final Device d : devices) { + MenuItem deviceItem = new MenuItem(manufacturerMenu, SWT.CHECK); + deviceItem.setText(d.getName()); + deviceItem.setSelection(current == d); + + deviceItem.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + selectDevice(d); + onDeviceChange(true /*recomputeLayout*/); + } + }); + } + } } @@ -1849,31 +1890,31 @@ public class ConfigurationComposite extends Composite implements SelectionListen if (event.detail == SWT.ARROW) { OrientationMenuAction.showMenu(ConfigurationComposite.this, combo); } else { - flipOrientation(); + gotoNextState(); } } }; combo.addListener(SWT.Selection, menuListener); } - /** Flip the current orientation to the next available device orientation, if any */ - private void flipOrientation() { - DeviceConfig config = getSelectedDeviceConfig(); - DeviceConfig flipped = getNextDeviceConfig(getSelectedDeviceConfig()); - if (flipped != config) { - selectDeviceConfig(flipped); + /** Move to the next device state, changing the icon if it changes orientation */ + private void gotoNextState() { + State state = getSelectedDeviceState(); + State flipped = getNextDeviceState(state); + if (flipped != state) { + selectDeviceState(flipped); onDeviceConfigChange(); } } - /** Get the next cyclical orientation after the given orientation */ + /** Get the next cyclical state after the given state */ @Nullable - DeviceConfig getNextDeviceConfig(DeviceConfig config) { - LayoutDevice device = getSelectedDevice(); - List<DeviceConfig> configs = device.getConfigs(); - for (int i = 0; i < configs.size(); i++) { - if (configs.get(i) == config) { - return configs.get((i + 1) % configs.size()); + State getNextDeviceState(State state) { + Device device = getSelectedDevice(); + List<State> states = device.getAllStates(); + for (int i = 0; i < states.size(); i++) { + if (states.get(i) == state) { + return states.get((i + 1) % states.size()); } } @@ -2304,13 +2345,13 @@ public class ConfigurationComposite extends Composite implements SelectionListen IProject project = mEditedFile.getProject(); ManifestInfo manifest = ManifestInfo.get(project); - // Look up the screen size for the current configuration + // Look up the screen size for the current state ScreenSize screenSize = null; if (mState.device != null) { - List<DeviceConfig> configs = mState.device.getConfigs(); - for (DeviceConfig config : configs) { + List<State> states = mState.device.getAllStates(); + for (State state : states) { ScreenSizeQualifier qualifier = - config.getConfig().getScreenSizeQualifier(); + DeviceConfigHelper.getFolderConfig(state).getScreenSizeQualifier(); screenSize = qualifier.getValue(); break; } @@ -2378,7 +2419,12 @@ public class ConfigurationComposite extends Composite implements SelectionListen */ public float getXDpi() { if (mState.device != null) { - float dpi = mState.device.getXDpi(); + + State currState = mState.device.getState(mState.stateName); + if (currState == null) { + currState = mState.device.getDefaultState(); + } + float dpi = (float) currState.getHardware().getScreen().getXdpi(); if (Float.isNaN(dpi) == false) { return dpi; } @@ -2393,7 +2439,12 @@ public class ConfigurationComposite extends Composite implements SelectionListen */ public float getYDpi() { if (mState.device != null) { - float dpi = mState.device.getYDpi(); + + State currState = mState.device.getState(mState.stateName); + if (currState == null) { + currState = mState.device.getDefaultState(); + } + float dpi = (float) currState.getHardware().getScreen().getYdpi(); if (Float.isNaN(dpi) == false) { return dpi; } @@ -2459,7 +2510,7 @@ public class ConfigurationComposite extends Composite implements SelectionListen * @return the device name, or null */ public String getDevice() { - LayoutDevice device = getSelectedDevice(); + Device device = getSelectedDevice(); if (device != null) { return device.getName(); } @@ -2530,24 +2581,22 @@ public class ConfigurationComposite extends Composite implements SelectionListen } /** - * Loads the list of {@link LayoutDevice} and inits the UI with it. + * Loads the list of {@link Device}s and inits the UI with it. */ private void initDevices() { - mDeviceList = null; - Sdk sdk = Sdk.getCurrent(); if (sdk != null) { - LayoutDeviceManager manager = sdk.getLayoutDeviceManager(); - mDeviceList = manager.getCombinedList(); + mDeviceList = sdk.getDevices(); + } else { + mDeviceList = new ArrayList<Device>(); } - // fill with the devices - if (mDeviceList != null && mDeviceList.size() > 0) { - LayoutDevice first = mDeviceList.get(0); + if (!mDeviceList.isEmpty()) { + Device first = mDeviceList.get(0); selectDevice(first); - List<DeviceConfig> configs = first.getConfigs(); - selectDeviceConfig(configs.get(0)); + List<State> states = first.getAllStates(); + selectDeviceState(states.get(0)); } else { selectDevice(null); } @@ -2580,11 +2629,11 @@ public class ConfigurationComposite extends Composite implements SelectionListen } @NonNull - ScreenOrientation getOrientation(DeviceConfig config) { - ScreenOrientationQualifier qualifier = config.getConfig().getScreenOrientationQualifier(); + ScreenOrientation getOrientation(State state) { + FolderConfiguration config = DeviceConfigHelper.getFolderConfig(state); ScreenOrientation orientation = null; - if (qualifier != null) { - orientation = qualifier.getValue(); + if (config != null && config.getScreenOrientationQualifier() != null) { + orientation = config.getScreenOrientationQualifier().getValue(); } if (orientation == null) { @@ -2594,24 +2643,24 @@ public class ConfigurationComposite extends Composite implements SelectionListen return orientation; } - void selectDeviceConfig(@Nullable DeviceConfig config) { - mOrientationCombo.setData(config); + void selectDeviceState(@Nullable State state) { + mOrientationCombo.setData(state); - DeviceConfig nextConfig = getNextDeviceConfig(config); - mOrientationCombo.setImage(getOrientationIcon(getOrientation(nextConfig), - nextConfig != config)); + State nextState = getNextDeviceState(state); + mOrientationCombo.setImage(getOrientationIcon(getOrientation(state), + nextState != state)); } - DeviceConfig getSelectedDeviceConfig() { - return (DeviceConfig) mOrientationCombo.getData(); + State getSelectedDeviceState() { + return (State) mOrientationCombo.getData(); } /** - * Selects a given {@link LayoutDevice} in the device combo, if it is found. + * Selects a given {@link Device} in the device combo, if it is found. * @param device the device to select * @return true if the device was found. */ - private boolean selectDevice(@Nullable LayoutDevice device) { + private boolean selectDevice(@Nullable Device device) { mDeviceCombo.setData(device); if (device != null) { mDeviceCombo.setText(getDeviceLabel(device, true)); @@ -2623,21 +2672,22 @@ public class ConfigurationComposite extends Composite implements SelectionListen return false; } - LayoutDevice getSelectedDevice() { - return (LayoutDevice) mDeviceCombo.getData(); + @Nullable + Device getSelectedDevice() { + return (Device) mDeviceCombo.getData(); } /** - * Selects a config by name. - * @param name the name of the config to select. + * Selects a state by name. + * @param name the name of the state to select. */ - private void selectConfig(String name) { - LayoutDevice device = getSelectedDevice(); - DeviceConfig config = null; + private void selectState(String name) { + Device device = getSelectedDevice(); + State state = null; if (device != null) { - config = device.getDeviceConfigByName(name); + state = device.getState(name); } - selectDeviceConfig(config); + selectDeviceState(state); } /** @@ -2653,17 +2703,16 @@ public class ConfigurationComposite extends Composite implements SelectionListen String newConfigName = null; - DeviceConfig prevConfig = getSelectedDeviceConfig(); - LayoutDevice device = getSelectedDevice(); - if (mState.device != null && prevConfig != null && device != null) { + State prevState = getSelectedDeviceState(); + Device device = getSelectedDevice(); + if (mState.device != null && prevState != null && device != null) { // get the previous config, so that we can look for a close match - FolderConfiguration oldConfig = mState.device.getFolderConfigByName( - prevConfig.getName()); - newConfigName = getClosestMatch(oldConfig, device.getConfigs()); + FolderConfiguration oldConfig = DeviceConfigHelper.getFolderConfig(prevState); + newConfigName = getClosestMatch(oldConfig, device.getAllStates()); } mState.device = device; - selectConfig(newConfigName); + selectState(newConfigName); computeCurrentConfig(); @@ -2673,80 +2722,37 @@ public class ConfigurationComposite extends Composite implements SelectionListen } /** - * Handles a user request for the {@link ConfigManagerDialog}. - */ - private void onCustomDeviceConfig() { - ConfigManagerDialog dialog = new ConfigManagerDialog(getShell()); - dialog.open(); - - // save the user devices - Sdk.getCurrent().getLayoutDeviceManager().save(); - - // Update the UI with no triggered event - mDisableUpdates++; - - try { - LayoutDevice oldCurrent = mState.device; - - // but first, update the device combo - initDevices(); - - // attempts to reselect the current device. - if (selectDevice(oldCurrent)) { - // current device still exists. - // reselect the config - selectConfig(mState.configName); - - // reset the UI as if it was just a replacement file, since we can keep - // the current device (and possibly config). - adaptConfigSelection(false /*needBestMatch*/); - - } else { - // find a new device/config to match the current file. - findAndSetCompatibleConfig(false /*favorCurrentConfig*/); - } - } finally { - mDisableUpdates--; - } - - // recompute the current config - computeCurrentConfig(); - - // force a redraw - onDeviceChange(true /*recomputeLayout*/); - } - - /** - * Attempts to find a close config among a list + * Attempts to find a close state among a list * @param oldConfig the reference config. - * @param configs the list of config to search through - * @return the name of the closest config match, or possibly null if no configs are compatible - * (this can only happen if the configs don't have a single qualifier that is the same). + * @param states the list of states to search through + * @return the name of the closest state match, or possibly null if no states are compatible + * (this can only happen if the states don't have a single qualifier that is the same). */ - private String getClosestMatch(FolderConfiguration oldConfig, List<DeviceConfig> configs) { + private String getClosestMatch(FolderConfiguration oldConfig, List<State> states) { - // create 2 lists as we're going to go through one and put the candidates in the other. - ArrayList<DeviceConfig> list1 = new ArrayList<DeviceConfig>(); - ArrayList<DeviceConfig> list2 = new ArrayList<DeviceConfig>(); + // create 2 lists as we're going to go through one and put the + // candidates in the other. + ArrayList<State> list1 = new ArrayList<State>(); + ArrayList<State> list2 = new ArrayList<State>(); - list1.addAll(configs); + list1.addAll(states); final int count = FolderConfiguration.getQualifierCount(); for (int i = 0 ; i < count ; i++) { - // compute the new candidate list by only taking configs that have - // the same i-th qualifier as the old config - for (DeviceConfig c : list1) { + // compute the new candidate list by only taking states that have + // the same i-th qualifier as the old state + for (State s : list1) { ResourceQualifier oldQualifier = oldConfig.getQualifier(i); - FolderConfiguration folderConfig = c.getConfig(); + FolderConfiguration folderConfig = DeviceConfigHelper.getFolderConfig(s); ResourceQualifier newQualifier = folderConfig.getQualifier(i); if (oldQualifier == null) { if (newQualifier == null) { - list2.add(c); + list2.add(s); } } else if (oldQualifier.equals(newQualifier)) { - list2.add(c); + list2.add(s); } } @@ -2756,9 +2762,9 @@ public class ConfigurationComposite extends Composite implements SelectionListen return list2.get(0).getName(); } - // if the list is empty, then all the new configs failed. It is considered ok, and + // if the list is empty, then all the new states failed. It is considered ok, and // we move to the next qualifier anyway. This way, if a qualifier is different for - // all new configs it is simply ignored. + // all new states it is simply ignored. if (list2.size() != 0) { // move the candidates back into list1. list1.clear(); @@ -2768,7 +2774,7 @@ public class ConfigurationComposite extends Composite implements SelectionListen } // the only way to reach this point is if there's an exact match. - // (if there are more than one, then there's a duplicate config and it doesn't matter, + // (if there are more than one, then there's a duplicate state and it doesn't matter, // we take the first one). if (list1.size() > 0) { return list1.get(0).getName(); @@ -2861,9 +2867,9 @@ public class ConfigurationComposite extends Composite implements SelectionListen saveState(); if (mState.device != null) { - // get the device config from the device/config combos. - FolderConfiguration config = mState.device.getFolderConfigByName( - getSelectedDeviceConfig().getName()); + // get the device config from the device/state combos. + FolderConfiguration config = + DeviceConfigHelper.getFolderConfig(getSelectedDeviceState()); // replace the config with the one from the device mCurrentConfig.set(config); @@ -2877,6 +2883,18 @@ public class ConfigurationComposite extends Composite implements SelectionListen (RegionQualifier)localeQualifiers[LOCALE_REGION]); } + // Replace the UiMode with the selected one, if one is selected + UiMode uiMode = getSelectedUiMode(); + if (uiMode != null) { + mCurrentConfig.setUiModeQualifier(new UiModeQualifier(uiMode)); + } + + // Replace the NightMode with the selected one, if one is selected + NightMode night = getSelectedNightMode(); + if (night != null) { + mCurrentConfig.setNightModeQualifier(new NightModeQualifier(night)); + } + // replace the API level by the selection of the combo IAndroidTarget target = getRenderingTarget(); if (target == null) { @@ -3209,7 +3227,7 @@ public class ConfigurationComposite extends Composite implements SelectionListen final Object source = e.getSource(); if (source == mOrientationCombo) { - flipOrientation(); + gotoNextState(); } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/OrientationMenuAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/OrientationMenuAction.java index c2f32c5..27446b2 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/OrientationMenuAction.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/OrientationMenuAction.java @@ -22,6 +22,10 @@ import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice.DeviceConfig; import com.android.resources.NightMode; import com.android.resources.ScreenOrientation; import com.android.resources.UiMode; +import com.android.sdklib.devices.Device; +import com.android.sdklib.devices.DeviceManager; +import com.android.sdklib.devices.State; + import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ActionContributionItem; @@ -59,19 +63,19 @@ class OrientationMenuAction extends SubmenuAction { MenuManager manager = new MenuManager(); // Show toggles for all the available configurations - DeviceConfig current = configuration.getSelectedDeviceConfig(); - LayoutDevice device = configuration.getSelectedDevice(); + State current = configuration.getSelectedDeviceState(); + Device device = configuration.getSelectedDevice(); if (device != null) { - List<DeviceConfig> configs = device.getConfigs(); + List<State> states = device.getAllStates(); - if (configs.size() > 1 && current != null) { - DeviceConfig flip = configuration.getNextDeviceConfig(current); + if (states.size() > 1 && current != null) { + State flip = configuration.getNextDeviceState(current); manager.add(new DeviceConfigAction(configuration, String.format("Switch to %1$s", flip.getName()), flip, false, true)); manager.add(new Separator()); } - for (DeviceConfig config : configs) { + for (State config : states) { manager.add(new DeviceConfigAction(configuration, config.getName(), config, config == current, false)); } @@ -150,23 +154,23 @@ class OrientationMenuAction extends SubmenuAction { private static class DeviceConfigAction extends Action { private final ConfigurationComposite mConfiguration; - private final DeviceConfig mConfig; + private final State mState; private DeviceConfigAction(ConfigurationComposite configuration, String title, - DeviceConfig config, boolean checked, boolean flip) { + State state, boolean checked, boolean flip) { super(title, IAction.AS_RADIO_BUTTON); mConfiguration = configuration; - mConfig = config; + mState = state; if (checked) { setChecked(true); } - ScreenOrientation orientation = configuration.getOrientation(config); + ScreenOrientation orientation = configuration.getOrientation(state); setImageDescriptor(configuration.getOrientationImage(orientation, flip)); } @Override public void run() { - mConfiguration.selectDeviceConfig(mConfig); + mConfiguration.selectDeviceState(mState); mConfiguration.onDeviceConfigChange(); } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java index 3fed2e0..79c9d62 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java @@ -44,6 +44,8 @@ import com.android.sdklib.IAndroidTarget; import com.android.sdklib.ISdkLog; import com.android.sdklib.SdkConstants; import com.android.sdklib.SdkManager; +import com.android.sdklib.devices.Device; +import com.android.sdklib.devices.DeviceManager; import com.android.sdklib.internal.avd.AvdManager; import com.android.sdklib.internal.project.ProjectProperties; import com.android.sdklib.internal.project.ProjectProperties.PropertyType; @@ -129,6 +131,7 @@ public final class Sdk { private final SdkManager mManager; private final DexWrapper mDexWrapper; private final AvdManager mAvdManager; + private final DeviceManager mDeviceManager; /** Map associating an {@link IAndroidTarget} to an {@link AndroidTargetData} */ private final HashMap<IAndroidTarget, AndroidTargetData> mTargetDataMap = @@ -145,8 +148,6 @@ public final class Sdk { private final String mDocBaseUrl; - private final LayoutDeviceManager mLayoutDeviceManager = new LayoutDeviceManager(); - /** * Classes implementing this interface will receive notification when targets are changed. */ @@ -662,8 +663,13 @@ public final class Sdk { } } - public LayoutDeviceManager getLayoutDeviceManager() { - return mLayoutDeviceManager; + public DeviceManager getDeviceManager() { + return mDeviceManager; + } + + /** Returns the devices provided by the SDK, including user created devices */ + public List<Device> getDevices() { + return mDeviceManager.getDevices(getSdkLocation()); } /** @@ -744,10 +750,7 @@ public final class Sdk { mDocBaseUrl = getDocumentationBaseUrl(mManager.getLocation() + SdkConstants.OS_SDK_DOCS_FOLDER); - // load the built-in and user layout devices - mLayoutDeviceManager.loadDefaultAndUserDevices(mManager.getLocation()); - // and the ones from the add-on - loadLayoutDevices(); + mDeviceManager = new DeviceManager(AdtPlugin.getDefault()); // update whatever ProjectState is already present with new IAndroidTarget objects. synchronized (LOCK) { @@ -826,24 +829,6 @@ public final class Sdk { } /** - * Parses the SDK add-ons to look for files called {@link SdkConstants#FN_DEVICES_XML} to - * load {@link LayoutDevice} from them. - */ - private void loadLayoutDevices() { - 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()) { - mLayoutDeviceManager.parseAddOnLayoutDevice(deviceXml); - } - } - } - - mLayoutDeviceManager.sealAddonLayoutDevices(); - } - - /** * Delegate listener for project changes. */ private IProjectListener mProjectListener = new IProjectListener() { diff --git a/eclipse/plugins/com.android.ide.eclipse.base/.classpath b/eclipse/plugins/com.android.ide.eclipse.base/.classpath index 9b4ea2f..5f09fc7 100644 --- a/eclipse/plugins/com.android.ide.eclipse.base/.classpath +++ b/eclipse/plugins/com.android.ide.eclipse.base/.classpath @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> + <classpathentry exported="true" kind="lib" path="libs/dvlib.jar"/> <classpathentry exported="true" kind="lib" path="libs/androidprefs.jar"/> <classpathentry exported="true" kind="lib" path="libs/common.jar"/> <classpathentry exported="true" kind="lib" path="libs/commons-codec-1.4.jar"/> diff --git a/eclipse/plugins/com.android.ide.eclipse.base/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.base/META-INF/MANIFEST.MF index b03048a..b16d89d 100644 --- a/eclipse/plugins/com.android.ide.eclipse.base/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.base/META-INF/MANIFEST.MF @@ -19,15 +19,18 @@ Bundle-ClassPath: ., libs/httpcore-4.1.jar, libs/httpmime-4.1.1.jar, libs/sdklib.jar, - libs/sdkstats.jar + libs/sdkstats.jar, + libs/dvlib.jar Export-Package: com.android, com.android.annotations, + com.android.dvlib, com.android.ide.eclipse.base, com.android.io, com.android.prefs, com.android.resources, com.android.sdklib, com.android.sdklib.build, + com.android.sdklib.devices, com.android.sdklib.internal.avd, com.android.sdklib.internal.build, com.android.sdklib.internal.project, diff --git a/eclipse/plugins/com.android.ide.eclipse.base/build.properties b/eclipse/plugins/com.android.ide.eclipse.base/build.properties index 6dcdd76..15e907d 100644 --- a/eclipse/plugins/com.android.ide.eclipse.base/build.properties +++ b/eclipse/plugins/com.android.ide.eclipse.base/build.properties @@ -12,6 +12,7 @@ bin.includes = .,\ libs/httpcore-4.1.jar,\ libs/httpmime-4.1.1.jar,\ libs/sdklib.jar,\ - libs/sdkstats.jar + libs/sdkstats.jar,\ + libs/dvlib.jar jars.compile.order = . source.. = src/ diff --git a/eclipse/scripts/create_all_symlinks.sh b/eclipse/scripts/create_all_symlinks.sh index dbc2cb8..6cf1fb2 100755 --- a/eclipse/scripts/create_all_symlinks.sh +++ b/eclipse/scripts/create_all_symlinks.sh @@ -108,7 +108,7 @@ CP_FILES="" ### BASE ### BASE_PLUGIN_DEST="sdk/eclipse/plugins/com.android.ide.eclipse.base/libs" -BASE_PLUGIN_LIBS="common sdkstats androidprefs sdklib" +BASE_PLUGIN_LIBS="common sdkstats androidprefs sdklib dvlib" BASE_PLUGIN_PREBUILTS="\ prebuilts/tools/common/commons-compress/commons-compress-1.0.jar \ prebuilts/tools/common/guava-tools/guava-10.0.1.jar \ diff --git a/ide_common/src/com/android/ide/common/resources/configuration/DeviceConfigHelper.java b/ide_common/src/com/android/ide/common/resources/configuration/DeviceConfigHelper.java index 7ed955f..27eaa01 100644 --- a/ide_common/src/com/android/ide/common/resources/configuration/DeviceConfigHelper.java +++ b/ide_common/src/com/android/ide/common/resources/configuration/DeviceConfigHelper.java @@ -17,6 +17,8 @@ package com.android.ide.common.resources.configuration; import com.android.annotations.Nullable; +import com.android.resources.NightMode; +import com.android.resources.UiMode; import com.android.sdklib.devices.Device; import com.android.sdklib.devices.Hardware; import com.android.sdklib.devices.Screen; @@ -64,6 +66,15 @@ public class DeviceConfigHelper { config.updateScreenWidthAndHeight(); + // Setup some default qualifiers + config.setUiModeQualifier(new UiModeQualifier(UiMode.NORMAL)); + config.setNightModeQualifier(new NightModeQualifier(NightMode.NOTNIGHT)); + config.setCountryCodeQualifier(new CountryCodeQualifier()); + config.setLanguageQualifier(new LanguageQualifier()); + config.setNetworkCodeQualifier(new NetworkCodeQualifier()); + config.setRegionQualifier(new RegionQualifier()); + config.setVersionQualifier(new VersionQualifier()); + return config; } diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceWriter.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceWriter.java index 3ecc55e..453a4e5 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceWriter.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceWriter.java @@ -90,6 +90,7 @@ public class DeviceWriter { Transformer tf = TransformerFactory.newInstance().newTransformer(); tf.setOutputProperty(OutputKeys.INDENT, "yes"); + tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); DOMSource source = new DOMSource(doc); StreamResult result = new StreamResult(out); tf.transform(source, result); diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java index 463037e..54e2fa7 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java @@ -140,6 +140,24 @@ public final class AvdInfo implements Comparable<AvdInfo> { return SdkConstants.CPU_ARCH_ARM; } + public String getDeviceManufacturer() { + String deviceManufacturer = mProperties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER); + if (deviceManufacturer != null && !deviceManufacturer.isEmpty()) { + return deviceManufacturer; + } + + return ""; + } + + public String getDeviceName() { + String deviceName = mProperties.get(AvdManager.AVD_INI_DEVICE_NAME); + if (deviceName != null && !deviceName.isEmpty()) { + return deviceName; + } + + return ""; + } + /** Convenience function to return a more user friendly name of the abi type. */ public static String getPrettyAbiType(String raw) { String s = null; diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java index 768a835..16bbb38 100644 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java @@ -86,6 +86,15 @@ public class AvdManager { */ public final static String AVD_INI_CPU_MODEL = "hw.cpu.model"; //$NON-NLS-1$ + /** + * AVD/config.ini key name representing the manufacturer of the device this avd was based on. + */ + public static final String AVD_INI_DEVICE_MANUFACTURER = "hw.device.manufacturer"; //$NON-NLS-1$ + + /** + * AVD/config.ini key name representing the name of the device this avd was based on. + */ + public static final String AVD_INI_DEVICE_NAME = "hw.device.name"; //$NON-NLS-1$ /** * AVD/config.ini key name representing the SDK-relative path of the skin folder, if any, diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java index 23835e1..0cf52cf 100644 --- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java +++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java @@ -573,6 +573,7 @@ final class AvdCreationDialog extends GridDialog { mStatusLabel.setText(" \n "); //$NON-NLS-1$ reloadTargetCombo(); + reloadDeviceCombo(); } /** @@ -763,9 +764,25 @@ final class AvdCreationDialog extends GridDialog { mAvdName.setText(mEditAvdInfo.getName()); + Map<String, String> props = mEditAvdInfo.getProperties(); + + if (props != null) { + // Try to match it to a device + + // The device has to be set before everything else because + // selecting a device will modify other options + for (int i = 0; i < mDeviceList.size(); i++){ + Device d = mDeviceList.get(i); + if(d.getManufacturer().equals(props.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER)) + && d.getName().equals(props.get(AvdManager.AVD_INI_DEVICE_NAME))) { + mDeviceCombo.select(i); + break; + } + } + } + IAndroidTarget target = mEditAvdInfo.getTarget(); if (target != null && !mCurrentTargets.isEmpty()) { - mDeviceCombo.setEnabled(true); // Try to select the target in the target combo. // This will fail if the AVD needs to be repaired. // @@ -776,6 +793,7 @@ final class AvdCreationDialog extends GridDialog { if (target.equals(mCurrentTargets.get(mTargetCombo.getItem(i)))) { mTargetCombo.select(i); reloadAbiTypeCombo(); + reloadDeviceCombo(); reloadSkinCombo(); break; } @@ -797,8 +815,8 @@ final class AvdCreationDialog extends GridDialog { } } - Map<String, String> props = mEditAvdInfo.getProperties(); if (props != null) { + // First try the skin name and if it doesn't work fallback on the skin path nextSkin: for (int s = 0; s < 2; s++) { String skin = props.get(s == 0 ? AvdManager.AVD_INI_SKIN_NAME @@ -885,15 +903,16 @@ final class AvdCreationDialog extends GridDialog { mProperties.remove(AvdManager.AVD_INI_SNAPSHOT_PRESENT); mProperties.remove(AvdManager.AVD_INI_IMAGES_1); mProperties.remove(AvdManager.AVD_INI_IMAGES_2); + mProperties.remove(AvdManager.AVD_INI_DEVICE_MANUFACTURER); + mProperties.remove(AvdManager.AVD_INI_DEVICE_NAME); mHardwareViewer.refresh(); } // Sets all of the other options based on the device currently selected in mDeviceCombo private void prefillWithDeviceConfig() { - int index = mDeviceCombo.getSelectionIndex(); - if (index >= 0 && index < mDeviceList.size()){ - Device d = mDeviceList.get(index); + Device d = getSelectedDevice(); + if (d != null) { Hardware hw = d.getDefaultHardware(); // Try setting the CPU/ABI @@ -1042,10 +1061,22 @@ final class AvdCreationDialog extends GridDialog { private void reloadDeviceCombo() { + Device selectedDevice = getSelectedDevice(); + + mDeviceCombo.removeAll(); for (Device d : mDeviceList) { mDeviceCombo.add(d.getManufacturer() + " " + d.getName()); } - mDeviceCombo.setEnabled(true); + + // Try to select the previously selected device if it still exists + if (selectedDevice != null) { + int index = mDeviceList.indexOf(selectedDevice); + if (index >= 0) { + mDeviceCombo.select(index); + } + } + + mDeviceCombo.setEnabled(mTargetCombo.getSelectionIndex() >= 0); } private void reloadSkinCombo() { @@ -1392,6 +1423,15 @@ final class AvdCreationDialog extends GridDialog { return false; } + targetIndex = mDeviceCombo.getSelectionIndex(); + if (targetIndex >= 0 && targetIndex < mDeviceList.size()) { + Device d = mDeviceList.get(targetIndex); + // Set the properties so it gets saved to the avd's ini + mProperties.put(AvdManager.AVD_INI_DEVICE_MANUFACTURER, d.getManufacturer()); + mProperties.put(AvdManager.AVD_INI_DEVICE_NAME, d.getName()); + } + + // resolve the target. String targetName = mTargetCombo.getItem(targetIndex); IAndroidTarget target = mCurrentTargets.get(targetName); @@ -1492,6 +1532,10 @@ final class AvdCreationDialog extends GridDialog { success = avdInfo != null; + // Remove the device name and manufacturer properties so they don't show up in the hardware list + mProperties.remove(AvdManager.AVD_INI_DEVICE_MANUFACTURER); + mProperties.remove(AvdManager.AVD_INI_DEVICE_NAME); + if (log instanceof MessageBoxLog) { ((MessageBoxLog) log).displayResult(success); } @@ -1524,6 +1568,15 @@ final class AvdCreationDialog extends GridDialog { return new ISystemImage[0]; } + private Device getSelectedDevice() { + int targetIndex = mDeviceCombo.getSelectionIndex(); + if (targetIndex >= 0 && mDeviceList.size() > targetIndex){ + return mDeviceList.get(targetIndex); + } else { + return null; + } + } + // End of hiding from SWT Designer //$hide<<$ } |