diff options
author | Xavier Ducrohet <xav@android.com> | 2010-07-28 17:01:55 -0700 |
---|---|---|
committer | Xavier Ducrohet <xav@android.com> | 2010-07-29 15:42:14 -0700 |
commit | 9498d202b8fbe9a7eff9ee209dc0575f8d8fac6d (patch) | |
tree | dac0e590e6983344ffb609211f7e7e4ac47a32b2 /eclipse/plugins | |
parent | 79de49d3c4108681d7a0381a4ff41ad70be24283 (diff) | |
download | sdk-9498d202b8fbe9a7eff9ee209dc0575f8d8fac6d.zip sdk-9498d202b8fbe9a7eff9ee209dc0575f8d8fac6d.tar.gz sdk-9498d202b8fbe9a7eff9ee209dc0575f8d8fac6d.tar.bz2 |
Don't rely on map to store layout device configs.
Relying on maps means that we don't control the order of the configs
in the UI. Mac/Windows show a different order already, and it's just
luck that the Mac one matches the content of the XML.
Now we keep the order from the XML and display it as-is in the UI.
Change-Id: I900f330a4ea9059fe27df2bca6c3a7a770737ae4
Diffstat (limited to 'eclipse/plugins')
4 files changed, 193 insertions, 83 deletions
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 index 8b585dd..6bfa9da 100644 --- 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 @@ -22,6 +22,7 @@ import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfi import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice; import com.android.ide.eclipse.adt.internal.sdk.LayoutDeviceManager; import com.android.ide.eclipse.adt.internal.sdk.Sdk; +import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice.DeviceConfig; import com.android.sdkuilib.ui.GridDialog; import org.eclipse.jface.dialogs.IDialogConstants; @@ -47,7 +48,7 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tree; -import java.util.Map; +import java.util.List; import java.util.Map.Entry; /** @@ -133,7 +134,7 @@ public class ConfigManagerDialog extends GridDialog { } } else if (parentElement instanceof LayoutDevice) { LayoutDevice device = (LayoutDevice)parentElement; - return device.getConfigs().entrySet().toArray(); + return device.getConfigs().toArray(); } return null; @@ -182,8 +183,7 @@ public class ConfigManagerDialog extends GridDialog { /** * Label provider for the {@link TreeViewer}. - * Supported elements are {@link DeviceType}, {@link LayoutDevice}, and {@link Entry} (where - * the key is a {@link String} object, and the value is a {@link FolderConfiguration} object). + * Supported elements are {@link DeviceType}, {@link LayoutDevice}, and {@link DeviceConfig}. * */ private final static class DeviceLabelProvider implements ITableLabelProvider { @@ -197,11 +197,11 @@ public class ConfigManagerDialog extends GridDialog { if (columnIndex == 0) { return ((LayoutDevice)element).getName(); } - } else if (element instanceof Entry<?, ?>) { + } else if (element instanceof DeviceConfig) { if (columnIndex == 0) { - return (String)((Entry<?,?>)element).getKey(); + return ((DeviceConfig)element).getName(); } else { - return ((Entry<?,?>)element).getValue().toString(); + return ((DeviceConfig)element).getConfig().toString(); } } return null; @@ -386,18 +386,18 @@ public class ConfigManagerDialog extends GridDialog { // are we copying the full device? if (selection.entry == null) { // get the config from the origin device - Map<String, FolderConfiguration> configs = selection.device.getConfigs(); + List<DeviceConfig> configs = selection.device.getConfigs(); // and copy them in the target device - for (Entry<String, FolderConfiguration> entry : configs.entrySet()) { + 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(entry.getValue()); + 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, entry.getKey(), copy); + mManager.addUserConfiguration(targetDevice, config.getName(), copy); } } else { // only copy the config. target device is not the same as the selection, don't @@ -533,12 +533,12 @@ public class ConfigManagerDialog extends GridDialog { // 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 Entry<?,?> + // this is more complex. we have the configName, but the tree contains DeviceConfig // Look for the entry. - Entry<?, ?> match = null; - for (Entry<?, ?> entry : device.getConfigs().entrySet()) { - if (entry.getKey().equals(configName)) { - match = entry; + DeviceConfig match = null; + for (DeviceConfig config : device.getConfigs()) { + if (config.getName().equals(configName)) { + match = config; break; } } 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 c267422..ef426df 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 @@ -39,6 +39,7 @@ import com.android.ide.eclipse.adt.internal.sdk.LayoutDeviceManager; import com.android.ide.eclipse.adt.internal.sdk.LoadStatus; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.LayoutBridge; +import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice.DeviceConfig; import com.android.layoutlib.api.IResourceValue; import com.android.layoutlib.api.IStyleResourceValue; import com.android.sdklib.IAndroidTarget; @@ -66,13 +67,12 @@ import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; +import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.SortedSet; -import java.util.Map.Entry; /** * A composite that displays the current configuration displayed in a Graphical Layout Editor. @@ -222,7 +222,7 @@ public class ConfigurationComposite extends Composite { for (LayoutDevice d : mDeviceList) { if (d.getName().equals(values[0])) { device = d; - FolderConfiguration config = device.getConfigs().get(values[1]); + FolderConfiguration config = device.getFolderConfigByName(values[1]); if (config != null) { configName = values[1]; @@ -731,9 +731,8 @@ public class ConfigurationComposite extends Composite { FolderConfiguration testConfig = new FolderConfiguration(); mainloop: for (LayoutDevice device : mDeviceList) { - for (Entry<String, FolderConfiguration> entry : - device.getConfigs().entrySet()) { - testConfig.set(entry.getValue()); + for (DeviceConfig config : device.getConfigs()) { + testConfig.set(config.getConfig()); // look on the locales. for (int i = 0 ; i < mLocaleList.size() ; i++) { @@ -748,14 +747,14 @@ public class ConfigurationComposite extends Composite { // where the edited file is a best config. if (anyDeviceMatch == null) { anyDeviceMatch = device; - anyConfigMatchName = entry.getKey(); + anyConfigMatchName = config.getName(); anyLocaleIndex = i; } if (isCurrentFileBestMatchFor(testConfig)) { // this is what we want. bestDeviceMatch = device; - bestConfigMatchName = entry.getKey(); + bestConfigMatchName = config.getName(); bestLocaleIndex = i; break mainloop; } @@ -823,7 +822,7 @@ public class ConfigurationComposite extends Composite { int configIndex = mDeviceConfigCombo.getSelectionIndex(); if (configIndex != -1) { String configName = mDeviceConfigCombo.getItem(configIndex); - FolderConfiguration currentConfig = mState.device.getConfigs().get(configName); + FolderConfiguration currentConfig = mState.device.getFolderConfigByName(configName); if (mEditedConfig.isMatchFor(currentConfig)) { currentConfigIsCompatible = true; // current config is compatible if (needBestMatch == false || isCurrentFileBestMatchFor(currentConfig)) { @@ -840,9 +839,8 @@ public class ConfigurationComposite extends Composite { // first look in the current device. String matchName = null; int localeIndex = -1; - Map<String, FolderConfiguration> configs = mState.device.getConfigs(); - mainloop: for (Entry<String, FolderConfiguration> entry : configs.entrySet()) { - testConfig.set(entry.getValue()); + mainloop: for (DeviceConfig config : mState.device.getConfigs()) { + testConfig.set(config.getConfig()); // loop on the locales. for (int i = 0 ; i < mLocaleList.size() ; i++) { @@ -854,7 +852,7 @@ public class ConfigurationComposite extends Composite { if (mEditedConfig.isMatchFor(testConfig) && isCurrentFileBestMatchFor(testConfig)) { - matchName = entry.getKey(); + matchName = config.getName(); localeIndex = i; break mainloop; } @@ -1303,13 +1301,12 @@ public class ConfigurationComposite extends Composite { mDeviceCombo.select(0); if (mDeviceList.size() > 0) { - Map<String, FolderConfiguration> configs = mDeviceList.get(0).getConfigs(); - Set<String> configNames = configs.keySet(); - for (String name : configNames) { - mDeviceConfigCombo.add(name); + List<DeviceConfig> configs = mDeviceList.get(0).getConfigs(); + for (DeviceConfig config : configs) { + mDeviceConfigCombo.add(config.getName()); } mDeviceConfigCombo.select(0); - if (configNames.size() == 1) { + if (configs.size() == 1) { mDeviceConfigCombo.setEnabled(false); } } @@ -1377,7 +1374,7 @@ public class ConfigurationComposite extends Composite { if (mState.device != null) { int index = mDeviceConfigCombo.getSelectionIndex(); if (index != -1) { - FolderConfiguration oldConfig = mState.device.getConfigs().get( + FolderConfiguration oldConfig = mState.device.getFolderConfigByName( mDeviceConfigCombo.getItem(index)); LayoutDevice newDevice = mDeviceList.get(deviceIndex); @@ -1449,40 +1446,37 @@ public class ConfigurationComposite extends Composite { * @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). */ - private String getClosestMatch(FolderConfiguration oldConfig, - Map<String, FolderConfiguration> configs) { + private String getClosestMatch(FolderConfiguration oldConfig, List<DeviceConfig> configs) { // create 2 lists as we're going to go through one and put the candidates in the other. - ArrayList<Entry<String, FolderConfiguration>> list1 = - new ArrayList<Entry<String,FolderConfiguration>>(); - ArrayList<Entry<String, FolderConfiguration>> list2 = - new ArrayList<Entry<String,FolderConfiguration>>(); + ArrayList<DeviceConfig> list1 = new ArrayList<DeviceConfig>(); + ArrayList<DeviceConfig> list2 = new ArrayList<DeviceConfig>(); - list1.addAll(configs.entrySet()); + list1.addAll(configs); 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 (Entry<String, FolderConfiguration> entry : list1) { + for (DeviceConfig c : list1) { ResourceQualifier oldQualifier = oldConfig.getQualifier(i); - FolderConfiguration config = entry.getValue(); - ResourceQualifier newQualifier = config.getQualifier(i); + FolderConfiguration folderConfig = c.getConfig(); + ResourceQualifier newQualifier = folderConfig.getQualifier(i); if (oldQualifier == null) { if (newQualifier == null) { - list2.add(entry); + list2.add(c); } } else if (oldQualifier.equals(newQualifier)) { - list2.add(entry); + list2.add(c); } } // at any moment if the new candidate list contains only one match, its name // is returned. if (list2.size() == 1) { - return list2.get(0).getKey(); + return list2.get(0).getName(); } // if the list is empty, then all the new configs failed. It is considered ok, and @@ -1500,7 +1494,7 @@ public class ConfigurationComposite extends Composite { // (if there are more than one, then there's a duplicate config and it doesn't matter, // we take the first one). if (list1.size() > 0) { - return list1.get(0).getKey(); + return list1.get(0).getName(); } return null; @@ -1514,22 +1508,20 @@ public class ConfigurationComposite extends Composite { mDeviceConfigCombo.removeAll(); if (mState.device != null) { - Set<String> configNames = mState.device.getConfigs().keySet(); - int selectionIndex = 0; int i = 0; - for (String name : configNames) { - mDeviceConfigCombo.add(name); + for (DeviceConfig config : mState.device.getConfigs()) { + mDeviceConfigCombo.add(config.getName()); - if (name.equals(refName)) { + if (config.getName().equals(refName)) { selectionIndex = i; } i++; } mDeviceConfigCombo.select(selectionIndex); - mDeviceConfigCombo.setEnabled(configNames.size() > 1); + mDeviceConfigCombo.setEnabled(mState.device.getConfigs().size() > 1); } } @@ -1588,7 +1580,7 @@ public class ConfigurationComposite extends Composite { // get the device config from the device/config combos. int configIndex = mDeviceConfigCombo.getSelectionIndex(); String name = mDeviceConfigCombo.getItem(configIndex); - FolderConfiguration config = mState.device.getConfigs().get(name); + FolderConfiguration config = mState.device.getFolderConfigByName(name); // replace the config with the one from the device mCurrentConfig.set(config); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutDevice.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutDevice.java index dd0fb74..4f7b7f2 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutDevice.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutDevice.java @@ -33,10 +33,9 @@ import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreen import org.w3c.dom.Document; import org.w3c.dom.Element; +import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; +import java.util.List; /** * Class representing a layout device. @@ -58,10 +57,35 @@ public class LayoutDevice { private final String mName; - /** editable map of the config */ - private Map<String, FolderConfiguration> mEditMap = new HashMap<String, FolderConfiguration>(); - /** unmodifiable map returned by {@link #getConfigs()}. */ - private Map<String, FolderConfiguration> mMap; + /** + * Wrapper around a {@link FolderConfiguration}. + * <p/>This adds a name, accessible through {@link #getName()}. + * <p/>The folder config can be accessed through {@link #getConfig()}. + * + */ + public final static class DeviceConfig { + private final String mName; + private final FolderConfiguration mConfig; + + DeviceConfig(String name, FolderConfiguration config) { + mName = name; + mConfig = config; + } + + public String getName() { + return mName; + } + + public FolderConfiguration getConfig() { + return mConfig; + } + } + + /** editable list of the config */ + private final ArrayList<DeviceConfig> mConfigs = new ArrayList<DeviceConfig>(); + /** Read-only list */ + private List<DeviceConfig> mROList; + private float mXDpi = Float.NaN; private float mYDpi = Float.NaN; @@ -93,8 +117,10 @@ public class LayoutDevice { } // then save all the configs. - for (Entry<String, FolderConfiguration> entry : mEditMap.entrySet()) { - saveConfigTo(doc, deviceNode, entry.getKey(), entry.getValue()); + synchronized (mConfigs) { + for (DeviceConfig config : mConfigs) { + saveConfigTo(doc, deviceNode, config.getName(), config.getConfig()); + } } } @@ -207,33 +233,91 @@ public class LayoutDevice { } } + /** + * Adds config to the LayoutDevice. + * <p/>This ensures that no two configurations have the same. If a config already exists + * with the same name, the new config replaces it. + * + * @param name the name of the config. + * @param config the config. + */ void addConfig(String name, FolderConfiguration config) { - mEditMap.put(name, config); - _seal(); + synchronized (mConfigs) { + doAddConfig(name, config); + seal(); + } } - void addConfigs(Map<String, FolderConfiguration> configs) { - mEditMap.putAll(configs); - _seal(); + /** + * Adds a list of config to the LayoutDevice + * <p/>This ensures that no two configurations have the same. If a config already exists + * with the same name, the new config replaces it. + + * @param configs the configs to add. + */ + void addConfigs(List<DeviceConfig> configs) { + synchronized (mConfigs) { + // add the configs manually one by one, to check for no duplicate. + for (DeviceConfig config : configs) { + String name = config.getName(); + + for (DeviceConfig c : mConfigs) { + if (c.getName().equals(name)) { + mConfigs.remove(c); + break; + } + } + + mConfigs.add(config); + } + + seal(); + } } + /** + * Removes a config by its name. + * @param name the name of the config to remove. + */ void removeConfig(String name) { - mEditMap.remove(name); - _seal(); + synchronized (mConfigs) { + for (DeviceConfig config : mConfigs) { + if (config.getName().equals(name)) { + mConfigs.remove(config); + seal(); + return; + } + } + } } /** - * Adds config to the LayoutDevice. This is to be used to add plenty of configurations. - * It must be followed by {@link #_seal()}. + * Adds config to the LayoutDevice. This is to be used to add plenty of + * configurations. It must be followed by {@link #_seal()}. + * <p/>This ensures that no two configurations have the same. If a config already exists + * with the same name, the new config replaces it. + * <p/><strong>This must be called inside a <code>synchronized(mConfigs)</code> block.</strong> + * * @param name the name of the config * @param config the config. */ - void _addConfig(String name, FolderConfiguration config) { - mEditMap.put(name, config); + private void doAddConfig(String name, FolderConfiguration config) { + // remove config that would have the same name to ensure no duplicate + for (DeviceConfig c : mConfigs) { + if (c.getName().equals(name)) { + mConfigs.remove(c); + break; + } + } + mConfigs.add(new DeviceConfig(name, config)); } - void _seal() { - mMap = Collections.unmodifiableMap(mEditMap); + /** + * Seals the layout device by setting up {@link #mROList}. + * <p/><strong>This must be called inside a <code>synchronized(mConfigs)</code> block.</strong> + */ + private void seal() { + mROList = Collections.unmodifiableList(mConfigs); } void setXDpi(float xdpi) { @@ -248,8 +332,43 @@ public class LayoutDevice { return mName; } - public Map<String, FolderConfiguration> getConfigs() { - return mMap; + /** + * Returns an unmodifiable list of all the {@link DeviceConfig}. + */ + public List<DeviceConfig> getConfigs() { + synchronized (mConfigs) { + return mROList; + } + } + + /** + * Returns a {@link DeviceConfig} by its name. + */ + public DeviceConfig getDeviceConfigByName(String name) { + synchronized (mConfigs) { + for (DeviceConfig config : mConfigs) { + if (config.getName().equals(name)) { + return config; + } + } + } + + return null; + } + + /** + * Returns a {@link FolderConfiguration} by its name. + */ + public FolderConfiguration getFolderConfigByName(String name) { + synchronized (mConfigs) { + for (DeviceConfig config : mConfigs) { + if (config.getName().equals(name)) { + return config.getConfig(); + } + } + } + + return null; } /** diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutDeviceManager.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutDeviceManager.java index 3b19f17..60c8d95 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutDeviceManager.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutDeviceManager.java @@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.internal.sdk; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration; +import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice.DeviceConfig; import com.android.prefs.AndroidLocation; import com.android.prefs.AndroidLocation.AndroidLocationException; import com.android.sdklib.SdkConstants; @@ -37,7 +38,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -180,7 +180,7 @@ public class LayoutDeviceManager { newDevice.setYDpi(newYDpi); // and get the Folderconfiguration - Map<String, FolderConfiguration> configs = device.getConfigs(); + List<DeviceConfig> configs = device.getConfigs(); newDevice.addConfigs(configs); // replace the old device with the new @@ -191,7 +191,6 @@ public class LayoutDeviceManager { return newDevice; } - /** * Adds or replaces a configuration in a given {@link LayoutDevice}. * @param device the device to modify |