diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationMatcher.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationMatcher.java | 843 |
1 files changed, 0 insertions, 843 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationMatcher.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationMatcher.java deleted file mode 100644 index 9724d4015..000000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationMatcher.java +++ /dev/null @@ -1,843 +0,0 @@ -/* - * Copyright (C) 2012 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.annotations.NonNull; -import com.android.annotations.Nullable; -import com.android.ide.common.resources.ResourceFile; -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.LocaleQualifier; -import com.android.ide.common.resources.configuration.NightModeQualifier; -import com.android.ide.common.resources.configuration.ResourceQualifier; -import com.android.ide.common.resources.configuration.ScreenOrientationQualifier; -import com.android.ide.common.resources.configuration.ScreenSizeQualifier; -import com.android.ide.common.resources.configuration.UiModeQualifier; -import com.android.ide.common.resources.configuration.VersionQualifier; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.AdtUtils; -import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; -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.Sdk; -import com.android.ide.eclipse.adt.io.IFileWrapper; -import com.android.resources.Density; -import com.android.resources.NightMode; -import com.android.resources.ResourceType; -import com.android.resources.ScreenOrientation; -import com.android.resources.ScreenSize; -import com.android.resources.UiMode; -import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.devices.Device; -import com.android.sdklib.devices.State; -import com.android.sdklib.repository.PkgProps; -import com.android.utils.Pair; -import com.android.utils.SparseIntArray; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.ui.IEditorPart; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * Produces matches for configurations - * <p> - * See algorithm described here: - * http://developer.android.com/guide/topics/resources/providing-resources.html - */ -public class ConfigurationMatcher { - private static final boolean PREFER_RECENT_RENDER_TARGETS = true; - - private final ConfigurationChooser mConfigChooser; - private final Configuration mConfiguration; - private final IFile mEditedFile; - private final ProjectResources mResources; - private final boolean mUpdateUi; - - ConfigurationMatcher(ConfigurationChooser chooser) { - this(chooser, chooser.getConfiguration(), chooser.getEditedFile(), - chooser.getResources(), true); - } - - ConfigurationMatcher( - @NonNull ConfigurationChooser chooser, - @NonNull Configuration configuration, - @Nullable IFile editedFile, - @Nullable ProjectResources resources, - boolean updateUi) { - mConfigChooser = chooser; - mConfiguration = configuration; - mEditedFile = editedFile; - mResources = resources; - mUpdateUi = updateUi; - } - - // ---- Finding matching configurations ---- - - private static class ConfigBundle { - private final FolderConfiguration config; - private int localeIndex; - private int dockModeIndex; - private int nightModeIndex; - - private ConfigBundle() { - config = new FolderConfiguration(); - } - - private ConfigBundle(ConfigBundle bundle) { - config = new FolderConfiguration(); - config.set(bundle.config); - localeIndex = bundle.localeIndex; - dockModeIndex = bundle.dockModeIndex; - nightModeIndex = bundle.nightModeIndex; - } - } - - private static class ConfigMatch { - final FolderConfiguration testConfig; - final Device device; - final State state; - final ConfigBundle bundle; - - public ConfigMatch(@NonNull FolderConfiguration testConfig, @NonNull Device device, - @NonNull State state, @NonNull ConfigBundle bundle) { - this.testConfig = testConfig; - this.device = device; - this.state = state; - this.bundle = bundle; - } - - @Override - public String toString() { - return device.getName() + " - " + state.getName(); - } - } - - /** - * Checks whether the current edited file is the best match for a given config. - * <p> - * This tests against other versions of the same layout in the project. - * <p> - * The given config must be compatible with the current edited file. - * @param config the config to test. - * @return true if the current edited file is the best match in the project for the - * given config. - */ - public boolean isCurrentFileBestMatchFor(FolderConfiguration config) { - ResourceFile match = mResources.getMatchingFile(mEditedFile.getName(), - ResourceType.LAYOUT, config); - - if (match != null) { - return match.getFile().equals(mEditedFile); - } else { - // if we stop here that means the current file is not even a match! - AdtPlugin.log(IStatus.ERROR, "Current file is not a match for the given config."); - } - - return false; - } - - /** - * Adapts the current device/config selection so that it's compatible with - * the configuration. - * <p> - * If the current selection is compatible, nothing is changed. - * <p> - * If it's not compatible, configs from the current devices are tested. - * <p> - * If none are compatible, it reverts to - * {@link #findAndSetCompatibleConfig(boolean)} - */ - void adaptConfigSelection(boolean needBestMatch) { - // check the device config (ie sans locale) - boolean needConfigChange = true; // if still true, we need to find another config. - boolean currentConfigIsCompatible = false; - State selectedState = mConfiguration.getDeviceState(); - FolderConfiguration editedConfig = mConfiguration.getEditedConfig(); - if (selectedState != null) { - FolderConfiguration currentConfig = DeviceConfigHelper.getFolderConfig(selectedState); - if (currentConfig != null && editedConfig.isMatchFor(currentConfig)) { - currentConfigIsCompatible = true; // current config is compatible - if (!needBestMatch || isCurrentFileBestMatchFor(currentConfig)) { - needConfigChange = false; - } - } - } - - if (needConfigChange) { - List<Locale> localeList = mConfigChooser.getLocaleList(); - - // 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. - State matchState = null; - int localeIndex = -1; - Device device = mConfiguration.getDevice(); - if (device != null) { - mainloop: for (State state : device.getAllStates()) { - testConfig.set(DeviceConfigHelper.getFolderConfig(state)); - - // loop on the locales. - for (int i = 0 ; i < localeList.size() ; i++) { - Locale locale = localeList.get(i); - - // update the test config with the locale qualifiers - testConfig.setLocaleQualifier(locale.qualifier); - - - if (editedConfig.isMatchFor(testConfig) && - isCurrentFileBestMatchFor(testConfig)) { - matchState = state; - localeIndex = i; - break mainloop; - } - } - } - } - - if (matchState != null) { - mConfiguration.setDeviceState(matchState, true); - Locale locale = localeList.get(localeIndex); - mConfiguration.setLocale(locale, true); - if (mUpdateUi) { - mConfigChooser.selectDeviceState(matchState); - mConfigChooser.selectLocale(locale); - } - mConfiguration.syncFolderConfig(); - } else { - // no match in current device with any state/locale - // attempt to find another device that can display this - // particular state. - findAndSetCompatibleConfig(currentConfigIsCompatible); - } - } - } - - /** - * Finds a device/config that can display a configuration. - * <p> - * Once found the device and config combos are set to the config. - * <p> - * If there is no compatible configuration, a custom one is created. - * - * @param favorCurrentConfig if true, and no best match is found, don't - * change the current config. This must only be true if the - * current config is compatible. - */ - void findAndSetCompatibleConfig(boolean favorCurrentConfig) { - List<Locale> localeList = mConfigChooser.getLocaleList(); - Collection<Device> devices = mConfigChooser.getDevices(); - FolderConfiguration editedConfig = mConfiguration.getEditedConfig(); - FolderConfiguration currentConfig = mConfiguration.getFullConfig(); - - // 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/state) - List<ConfigMatch> bestMatches = new ArrayList<ConfigMatch>(); - - // get a locale that match the host locale roughly (may not be exact match on the region.) - int localeHostMatch = getLocaleMatch(); - - // build a list of combinations of non standard qualifiers to add to each device's - // qualifier set when testing for a match. - // These qualifiers are: locale, night-mode, car dock. - List<ConfigBundle> configBundles = new ArrayList<ConfigBundle>(200); - - // If the edited file has locales, then we have to select a matching locale from - // the list. - // However, if it doesn't, we don't randomly take the first locale, we take one - // matching the current host locale (making sure it actually exist in the project) - int start, max; - if (editedConfig.getLocaleQualifier() != null || localeHostMatch == -1) { - // add all the locales - start = 0; - max = localeList.size(); - } else { - // only add the locale host match - start = localeHostMatch; - max = localeHostMatch + 1; // test is < - } - - for (int i = start ; i < max ; i++) { - Locale l = localeList.get(i); - - ConfigBundle bundle = new ConfigBundle(); - bundle.config.setLocaleQualifier(l.qualifier); - - bundle.localeIndex = i; - configBundles.add(bundle); - } - - // add the dock mode to the bundle combinations. - addDockModeToBundles(configBundles); - - // add the night mode to the bundle combinations. - addNightModeToBundles(configBundles); - - addRenderTargetToBundles(configBundles); - - for (Device device : devices) { - for (State state : device.getAllStates()) { - - // 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(stateConfig); - - // add on top of it, the extra qualifiers from the bundle - testConfig.add(bundle.config); - - if (editedConfig.isMatchFor(testConfig)) { - // 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, state, bundle)); - - if (isCurrentFileBestMatchFor(testConfig)) { - // this is what we want. - bestMatches.add(new ConfigMatch(testConfig, device, state, bundle)); - } - } - } - } - } - - if (bestMatches.size() == 0) { - if (favorCurrentConfig) { - // quick check - if (!editedConfig.isMatchFor(currentConfig)) { - AdtPlugin.log(IStatus.ERROR, - "favorCurrentConfig can only be true if the current config is compatible"); - } - - // just display the warning - AdtPlugin.printErrorToConsole(mEditedFile.getProject(), - String.format( - "'%1$s' is not a best match for any device/locale combination.", - editedConfig.toDisplayString()), - String.format( - "Displaying it with '%1$s'", - currentConfig.toDisplayString())); - } else if (anyMatches.size() > 0) { - // select the best device anyway. - ConfigMatch match = selectConfigMatch(anyMatches); - mConfiguration.setDevice(match.device, true); - mConfiguration.setDeviceState(match.state, true); - mConfiguration.setLocale(localeList.get(match.bundle.localeIndex), true); - mConfiguration.setUiMode(UiMode.getByIndex(match.bundle.dockModeIndex), true); - mConfiguration.setNightMode(NightMode.getByIndex(match.bundle.nightModeIndex), - true); - - if (mUpdateUi) { - mConfigChooser.selectDevice(mConfiguration.getDevice()); - mConfigChooser.selectDeviceState(mConfiguration.getDeviceState()); - mConfigChooser.selectLocale(mConfiguration.getLocale()); - } - - mConfiguration.syncFolderConfig(); - - // TODO: display a better warning! - AdtPlugin.printErrorToConsole(mEditedFile.getProject(), - String.format( - "'%1$s' is not a best match for any device/locale combination.", - editedConfig.toDisplayString()), - String.format( - "Displaying it with '%1$s' which is compatible, but will " + - "actually be displayed with another more specific version of " + - "the layout.", - currentConfig.toDisplayString())); - - } 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 state, - // and replace whatever qualifier required by the layout file. - } - } else { - ConfigMatch match = selectConfigMatch(bestMatches); - mConfiguration.setDevice(match.device, true); - mConfiguration.setDeviceState(match.state, true); - mConfiguration.setLocale(localeList.get(match.bundle.localeIndex), true); - mConfiguration.setUiMode(UiMode.getByIndex(match.bundle.dockModeIndex), true); - mConfiguration.setNightMode(NightMode.getByIndex(match.bundle.nightModeIndex), true); - - mConfiguration.syncFolderConfig(); - - if (mUpdateUi) { - mConfigChooser.selectDevice(mConfiguration.getDevice()); - mConfigChooser.selectDeviceState(mConfiguration.getDeviceState()); - mConfigChooser.selectLocale(mConfiguration.getLocale()); - } - } - } - - private void addRenderTargetToBundles(List<ConfigBundle> configBundles) { - Pair<Locale, IAndroidTarget> state = Configuration.loadRenderState(mConfigChooser); - if (state != null) { - IAndroidTarget target = state.getSecond(); - if (target != null) { - int apiLevel = target.getVersion().getApiLevel(); - for (ConfigBundle bundle : configBundles) { - bundle.config.setVersionQualifier( - new VersionQualifier(apiLevel)); - } - } - } - } - - private void addDockModeToBundles(List<ConfigBundle> addConfig) { - ArrayList<ConfigBundle> list = new ArrayList<ConfigBundle>(); - - // loop on each item and for each, add all variations of the dock modes - for (ConfigBundle bundle : addConfig) { - int index = 0; - for (UiMode mode : UiMode.values()) { - ConfigBundle b = new ConfigBundle(bundle); - b.config.setUiModeQualifier(new UiModeQualifier(mode)); - b.dockModeIndex = index++; - list.add(b); - } - } - - addConfig.clear(); - addConfig.addAll(list); - } - - private void addNightModeToBundles(List<ConfigBundle> addConfig) { - ArrayList<ConfigBundle> list = new ArrayList<ConfigBundle>(); - - // loop on each item and for each, add all variations of the night modes - for (ConfigBundle bundle : addConfig) { - int index = 0; - for (NightMode mode : NightMode.values()) { - ConfigBundle b = new ConfigBundle(bundle); - b.config.setNightModeQualifier(new NightModeQualifier(mode)); - b.nightModeIndex = index++; - list.add(b); - } - } - - addConfig.clear(); - addConfig.addAll(list); - } - - private int getLocaleMatch() { - java.util.Locale defaultLocale = java.util.Locale.getDefault(); - if (defaultLocale != null) { - String currentLanguage = defaultLocale.getLanguage(); - String currentRegion = defaultLocale.getCountry(); - - List<Locale> localeList = mConfigChooser.getLocaleList(); - final int count = localeList.size(); - for (int l = 0; l < count; l++) { - Locale locale = localeList.get(l); - LocaleQualifier qualifier = locale.qualifier; - - // there's always a ##/Other or ##/Any (which is the same, the region - // contains FAKE_REGION_VALUE). If we don't find a perfect region match - // we take the fake region. Since it's last in the list, this makes the - // test easy. - if (qualifier.getLanguage().equals(currentLanguage) && - (qualifier.getRegion() == null || qualifier.getRegion().equals(currentRegion))) { - return l; - } - } - - // if no locale match the current local locale, it's likely that it is - // the default one which is the last one. - return count - 1; - } - - return -1; - } - - private ConfigMatch selectConfigMatch(List<ConfigMatch> matches) { - // API 11-13: look for a x-large device - Comparator<ConfigMatch> comparator = null; - Sdk sdk = Sdk.getCurrent(); - if (sdk != null) { - IAndroidTarget projectTarget = sdk.getTarget(mEditedFile.getProject()); - if (projectTarget != null) { - int apiLevel = projectTarget.getVersion().getApiLevel(); - if (apiLevel >= 11 && apiLevel < 14) { - // TODO: Maybe check the compatible-screen tag in the manifest to figure out - // what kind of device should be used for display. - comparator = new TabletConfigComparator(); - } - } - } - if (comparator == null) { - // lets look for a high density device - comparator = new PhoneConfigComparator(); - } - Collections.sort(matches, comparator); - - // Look at the currently active editor to see if it's a layout editor, and if so, - // look up its configuration and if the configuration is in our match list, - // use it. This means we "preserve" the current configuration when you open - // new layouts. - IEditorPart activeEditor = AdtUtils.getActiveEditor(); - LayoutEditorDelegate delegate = LayoutEditorDelegate.fromEditor(activeEditor); - if (delegate != null - // (Only do this when the two files are in the same project) - && delegate.getEditor().getProject() == mEditedFile.getProject()) { - FolderConfiguration configuration = delegate.getGraphicalEditor().getConfiguration(); - if (configuration != null) { - for (ConfigMatch match : matches) { - if (configuration.equals(match.testConfig)) { - return match; - } - } - } - } - - // the list has been sorted so that the first item is the best config - return matches.get(0); - } - - /** Return the default render target to use, or null if no strong preference */ - @Nullable - static IAndroidTarget findDefaultRenderTarget(ConfigurationChooser chooser) { - if (PREFER_RECENT_RENDER_TARGETS) { - // Use the most recent target - List<IAndroidTarget> targetList = chooser.getTargetList(); - if (!targetList.isEmpty()) { - return targetList.get(targetList.size() - 1); - } - } - - IProject project = chooser.getProject(); - // Default to layoutlib version 5 - Sdk current = Sdk.getCurrent(); - if (current != null) { - IAndroidTarget projectTarget = current.getTarget(project); - int minProjectApi = Integer.MAX_VALUE; - if (projectTarget != null) { - if (!projectTarget.isPlatform() && projectTarget.hasRenderingLibrary()) { - // Renderable non-platform targets are all going to be adequate (they - // will have at least version 5 of layoutlib) so use the project - // target as the render target. - return projectTarget; - } - - if (projectTarget.getVersion().isPreview() - && projectTarget.hasRenderingLibrary()) { - // If the project target is a preview version, then just use it - return projectTarget; - } - - minProjectApi = projectTarget.getVersion().getApiLevel(); - } - - // We want to pick a render target that contains at least version 5 (and - // preferably version 6) of the layout library. To do this, we go through the - // targets and pick the -smallest- API level that is both simultaneously at - // least as big as the project API level, and supports layoutlib level 5+. - IAndroidTarget best = null; - int bestApiLevel = Integer.MAX_VALUE; - - for (IAndroidTarget target : current.getTargets()) { - // Non-platform targets are not chosen as the default render target - if (!target.isPlatform()) { - continue; - } - - int apiLevel = target.getVersion().getApiLevel(); - - // Ignore targets that have a lower API level than the minimum project - // API level: - if (apiLevel < minProjectApi) { - continue; - } - - // Look up the layout lib API level. This property is new so it will only - // be defined for version 6 or higher, which means non-null is adequate - // to see if this target is eligible: - String property = target.getProperty(PkgProps.LAYOUTLIB_API); - // In addition, Android 3.0 with API level 11 had version 5.0 which is adequate: - if (property != null || apiLevel >= 11) { - if (apiLevel < bestApiLevel) { - bestApiLevel = apiLevel; - best = target; - } - } - } - - return best; - } - - return null; - } - - /** - * Attempts to find a close state among a list - * - * @param oldConfig the reference config. - * @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). - */ - @Nullable - static String getClosestMatch(@NonNull FolderConfiguration oldConfig, - @NonNull List<State> states) { - - // create 2 lists as we're going to go through one and put the - // candidates in the other. - List<State> list1 = new ArrayList<State>(states.size()); - List<State> list2 = new ArrayList<State>(states.size()); - - list1.addAll(states); - - final int count = FolderConfiguration.getQualifierCount(); - for (int i = 0 ; i < count ; i++) { - // 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 = DeviceConfigHelper.getFolderConfig(s); - ResourceQualifier newQualifier = - folderConfig != null ? folderConfig.getQualifier(i) : null; - - if (oldQualifier == null) { - if (newQualifier == null) { - list2.add(s); - } - } else if (oldQualifier.equals(newQualifier)) { - list2.add(s); - } - } - - // at any moment if the new candidate list contains only one match, its name - // is returned. - if (list2.size() == 1) { - return list2.get(0).getName(); - } - - // 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 states it is simply ignored. - if (list2.size() != 0) { - // move the candidates back into list1. - list1.clear(); - list1.addAll(list2); - list2.clear(); - } - } - - // 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 state and it doesn't matter, - // we take the first one). - if (list1.size() > 0) { - return list1.get(0).getName(); - } - - return null; - } - - /** - * Returns the layout {@link IFile} which best matches the configuration - * selected in the given configuration chooser. - * - * @param chooser the associated configuration chooser holding project state - * @return the file which best matches the settings - */ - @Nullable - public static IFile getBestFileMatch(ConfigurationChooser chooser) { - // get the resources of the file's project. - ResourceManager manager = ResourceManager.getInstance(); - ProjectResources resources = manager.getProjectResources(chooser.getProject()); - if (resources == null) { - return null; - } - - // From the resources, look for a matching file - IFile editedFile = chooser.getEditedFile(); - if (editedFile == null) { - return null; - } - String name = editedFile.getName(); - FolderConfiguration config = chooser.getConfiguration().getFullConfig(); - ResourceFile match = resources.getMatchingFile(name, ResourceType.LAYOUT, config); - - if (match != null) { - // In Eclipse, the match's file is always an instance of IFileWrapper - return ((IFileWrapper) match.getFile()).getIFile(); - } - - return null; - } - - /** - * Note: this comparator imposes orderings that are inconsistent with equals. - */ - private static class TabletConfigComparator implements Comparator<ConfigMatch> { - @Override - public int compare(ConfigMatch o1, ConfigMatch o2) { - FolderConfiguration config1 = o1 != null ? o1.testConfig : null; - FolderConfiguration config2 = o2 != null ? o2.testConfig : null; - if (config1 == null) { - if (config2 == null) { - return 0; - } else { - return -1; - } - } else if (config2 == null) { - return 1; - } - - ScreenSizeQualifier size1 = config1.getScreenSizeQualifier(); - ScreenSizeQualifier size2 = config2.getScreenSizeQualifier(); - ScreenSize ss1 = size1 != null ? size1.getValue() : ScreenSize.NORMAL; - ScreenSize ss2 = size2 != null ? size2.getValue() : ScreenSize.NORMAL; - - // X-LARGE is better than all others (which are considered identical) - // if both X-LARGE, then LANDSCAPE is better than all others (which are identical) - - if (ss1 == ScreenSize.XLARGE) { - if (ss2 == ScreenSize.XLARGE) { - ScreenOrientationQualifier orientation1 = - config1.getScreenOrientationQualifier(); - ScreenOrientation so1 = orientation1.getValue(); - if (so1 == null) { - so1 = ScreenOrientation.PORTRAIT; - } - ScreenOrientationQualifier orientation2 = - config2.getScreenOrientationQualifier(); - ScreenOrientation so2 = orientation2.getValue(); - if (so2 == null) { - so2 = ScreenOrientation.PORTRAIT; - } - - if (so1 == ScreenOrientation.LANDSCAPE) { - if (so2 == ScreenOrientation.LANDSCAPE) { - return 0; - } else { - return -1; - } - } else if (so2 == ScreenOrientation.LANDSCAPE) { - return 1; - } else { - return 0; - } - } else { - return -1; - } - } else if (ss2 == ScreenSize.XLARGE) { - return 1; - } else { - return 0; - } - } - } - - /** - * Note: this comparator imposes orderings that are inconsistent with equals. - */ - private static class PhoneConfigComparator implements Comparator<ConfigMatch> { - - private final SparseIntArray mDensitySort = new SparseIntArray(4); - - public PhoneConfigComparator() { - // put the sort order for the density. - mDensitySort.put(Density.HIGH.getDpiValue(), 1); - mDensitySort.put(Density.MEDIUM.getDpiValue(), 2); - mDensitySort.put(Density.XHIGH.getDpiValue(), 3); - mDensitySort.put(Density.LOW.getDpiValue(), 4); - } - - @Override - public int compare(ConfigMatch o1, ConfigMatch o2) { - FolderConfiguration config1 = o1 != null ? o1.testConfig : null; - FolderConfiguration config2 = o2 != null ? o2.testConfig : null; - if (config1 == null) { - if (config2 == null) { - return 0; - } else { - return -1; - } - } else if (config2 == null) { - return 1; - } - - int dpi1 = Density.DEFAULT_DENSITY; - int dpi2 = Density.DEFAULT_DENSITY; - - DensityQualifier dpiQualifier1 = config1.getDensityQualifier(); - if (dpiQualifier1 != null) { - Density value = dpiQualifier1.getValue(); - dpi1 = value != null ? value.getDpiValue() : Density.DEFAULT_DENSITY; - } - dpi1 = mDensitySort.get(dpi1, 100 /* valueIfKeyNotFound*/); - - DensityQualifier dpiQualifier2 = config2.getDensityQualifier(); - if (dpiQualifier2 != null) { - Density value = dpiQualifier2.getValue(); - dpi2 = value != null ? value.getDpiValue() : Density.DEFAULT_DENSITY; - } - dpi2 = mDensitySort.get(dpi2, 100 /* valueIfKeyNotFound*/); - - if (dpi1 == dpi2) { - // portrait is better - ScreenOrientation so1 = ScreenOrientation.PORTRAIT; - ScreenOrientationQualifier orientationQualifier1 = - config1.getScreenOrientationQualifier(); - if (orientationQualifier1 != null) { - so1 = orientationQualifier1.getValue(); - if (so1 == null) { - so1 = ScreenOrientation.PORTRAIT; - } - } - ScreenOrientation so2 = ScreenOrientation.PORTRAIT; - ScreenOrientationQualifier orientationQualifier2 = - config2.getScreenOrientationQualifier(); - if (orientationQualifier2 != null) { - so2 = orientationQualifier2.getValue(); - if (so2 == null) { - so2 = ScreenOrientation.PORTRAIT; - } - } - - if (so1 == ScreenOrientation.PORTRAIT) { - if (so2 == ScreenOrientation.PORTRAIT) { - return 0; - } else { - return -1; - } - } else if (so2 == ScreenOrientation.PORTRAIT) { - return 1; - } else { - return 0; - } - } - - return dpi1 - dpi2; - } - } -} |