| /* |
| * Copyright (C) 2008 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.eclipse.adt.internal.editors.IconFactory; |
| import com.android.ide.eclipse.adt.internal.resources.ResourceType; |
| import com.android.ide.eclipse.adt.internal.resources.configurations.CountryCodeQualifier; |
| import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration; |
| import com.android.ide.eclipse.adt.internal.resources.configurations.LanguageQualifier; |
| import com.android.ide.eclipse.adt.internal.resources.configurations.NetworkCodeQualifier; |
| import com.android.ide.eclipse.adt.internal.resources.configurations.RegionQualifier; |
| import com.android.ide.eclipse.adt.internal.resources.configurations.ResourceQualifier; |
| import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenDimensionQualifier; |
| import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier; |
| import com.android.ide.eclipse.adt.internal.resources.configurations.VersionQualifier; |
| import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier.ScreenOrientation; |
| import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources; |
| import com.android.ide.eclipse.adt.internal.sdk.DeviceConfiguration; |
| import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.LanguageRegionVerifier; |
| import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.MobileCodeVerifier; |
| import com.android.layoutlib.api.IResourceValue; |
| import com.android.layoutlib.api.IStyleResourceValue; |
| |
| import org.eclipse.draw2d.geometry.Rectangle; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.ModifyEvent; |
| import org.eclipse.swt.events.ModifyListener; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| 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.Combo; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Text; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.SortedSet; |
| |
| /** |
| * A composite that displays the current configuration displayed in a Graphical Layout Editor. |
| */ |
| public class ConfigurationComposite extends Composite { |
| |
| private final static String THEME_SEPARATOR = "----------"; //$NON-NLS-1$ |
| |
| private Text mCountry; |
| private Text mNetwork; |
| private Combo mLocale; |
| private Combo mDeviceList; |
| private Combo mDeviceConfigs; |
| private Combo mThemeCombo; |
| private Button mCreateButton; |
| |
| private Label mCountryIcon; |
| private Label mNetworkIcon; |
| |
| private Label mCurrentLayoutLabel; |
| |
| private Image mMatchImage; |
| private Image mErrorImage; |
| |
| private int mPlatformThemeCount = 0; |
| private boolean mDisableUpdates = false; |
| |
| /** The {@link FolderConfiguration} representing the state of the UI controls */ |
| private final FolderConfiguration mCurrentConfig = new FolderConfiguration(); |
| |
| private DeviceConfiguration[] mDevices; |
| |
| private final ArrayList<ResourceQualifier[] > mLocaleList = |
| new ArrayList<ResourceQualifier[]>(); |
| |
| private final IConfigListener mListener; |
| |
| /** |
| * Interface implemented by the part which owns a {@link ConfigurationComposite}. |
| * This notifies the owners when the configuration change. |
| * The owner must also provide methods to provide the configuration that will |
| * be displayed. |
| */ |
| public interface IConfigListener { |
| void onConfigurationChange(); |
| void onThemeChange(); |
| void onCreate(); |
| |
| ProjectResources getProjectResources(); |
| ProjectResources getFrameworkResources(); |
| Map<String, Map<String, IResourceValue>> getConfiguredProjectResources(); |
| Map<String, Map<String, IResourceValue>> getConfiguredFrameworkResources(); |
| } |
| |
| public ConfigurationComposite(IConfigListener listener, Composite parent, int style) { |
| super(parent, style); |
| mListener = listener; |
| mDevices = DeviceConfiguration.getDevices(); |
| |
| IconFactory factory = IconFactory.getInstance(); |
| mMatchImage = factory.getIcon("match"); //$NON-NLS-1$ |
| mErrorImage = factory.getIcon("error"); //$NON-NLS-1$ |
| |
| GridLayout gl; |
| GridData gd; |
| int cols = 10; |
| |
| setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| setLayout(gl = new GridLayout(cols, false)); |
| |
| new Label(this, SWT.NONE).setText("MCC"); |
| mCountryIcon = createControlComposite(this, true /* grab_horizontal */); |
| mCountry = new Text(mCountryIcon.getParent(), SWT.BORDER); |
| mCountry.setLayoutData(new GridData( |
| GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); |
| mCountry.addVerifyListener(new MobileCodeVerifier()); |
| mCountry.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetDefaultSelected(SelectionEvent e) { |
| onCountryCodeChange(); |
| } |
| }); |
| mCountry.addModifyListener(new ModifyListener() { |
| public void modifyText(ModifyEvent e) { |
| onCountryCodeChange(); |
| } |
| }); |
| |
| new Label(this, SWT.NONE).setText("MNC"); |
| mNetworkIcon = createControlComposite(this, true /* grab_horizontal */); |
| mNetwork = new Text(mNetworkIcon.getParent(), SWT.BORDER); |
| mNetwork.setLayoutData(new GridData( |
| GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); |
| mNetwork.addVerifyListener(new MobileCodeVerifier()); |
| mNetwork.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetDefaultSelected(SelectionEvent e) { |
| onNetworkCodeChange(); |
| } |
| }); |
| mNetwork.addModifyListener(new ModifyListener() { |
| public void modifyText(ModifyEvent e) { |
| onNetworkCodeChange(); |
| } |
| }); |
| |
| new Label(this, SWT.NONE).setText("Locale"); |
| mLocale = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); |
| mLocale.setLayoutData(new GridData( |
| GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); |
| mLocale.addVerifyListener(new LanguageRegionVerifier()); |
| mLocale.addSelectionListener(new SelectionListener() { |
| public void widgetDefaultSelected(SelectionEvent e) { |
| onLocaleChange(); |
| } |
| public void widgetSelected(SelectionEvent e) { |
| onLocaleChange(); |
| } |
| }); |
| |
| new Label(this, SWT.NONE).setText("Devices"); |
| mDeviceList = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); |
| // fill with the devices |
| for (DeviceConfiguration device : mDevices) { |
| mDeviceList.add(device.getName()); |
| } |
| |
| mDeviceList.select(0); |
| mDeviceList.setLayoutData(new GridData( |
| GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); |
| mDeviceList.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| onDeviceChange(); |
| } |
| }); |
| |
| new Label(this, SWT.NONE).setText("Config"); |
| mDeviceConfigs = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); |
| Map<String, FolderConfiguration> configs = mDevices[0].getConfigs(); |
| Set<String> configNames = configs.keySet(); |
| for (String name : configNames) { |
| mDeviceConfigs.add(name); |
| } |
| mDeviceConfigs.select(0); |
| if (configNames.size() == 1) { |
| mDeviceConfigs.setEnabled(false); |
| } |
| mDeviceConfigs.setLayoutData(new GridData( |
| GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); |
| mDeviceConfigs.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| onDeviceConfigChange(); |
| } |
| }); |
| |
| Composite labelParent = new Composite(this, SWT.NONE); |
| labelParent.setLayout(gl = new GridLayout(8, false)); |
| gl.marginWidth = gl.marginHeight = 0; |
| labelParent.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); |
| gd.horizontalSpan = cols; |
| |
| new Label(labelParent, SWT.NONE).setText("Editing config:"); |
| mCurrentLayoutLabel = new Label(labelParent, SWT.NONE); |
| mCurrentLayoutLabel.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL)); |
| gd.widthHint = 50; |
| |
| // first separator |
| Label separator = new Label(labelParent, SWT.SEPARATOR | SWT.VERTICAL); |
| separator.setLayoutData(gd = new GridData( |
| GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL)); |
| gd.heightHint = 0; |
| |
| mThemeCombo = new Combo(labelParent, SWT.READ_ONLY | SWT.DROP_DOWN); |
| mThemeCombo.setEnabled(false); |
| updateUIFromResources(); |
| mThemeCombo.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| onThemeChange(); |
| } |
| }); |
| |
| // second separator |
| separator = new Label(labelParent, SWT.SEPARATOR | SWT.VERTICAL); |
| separator.setLayoutData(gd = new GridData( |
| GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL)); |
| gd.heightHint = 0; |
| |
| mCreateButton = new Button(labelParent, SWT.PUSH | SWT.FLAT); |
| mCreateButton.setText("Create..."); |
| mCreateButton.setEnabled(false); |
| mCreateButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| if (mListener != null) { |
| mListener.onCreate(); |
| } |
| } |
| }); |
| |
| onDeviceConfigChange(); |
| } |
| |
| public void setConfig(FolderConfiguration config) { |
| // mCurrentConfig.set(config); |
| throw new UnsupportedOperationException("setConfig"); |
| } |
| |
| public FolderConfiguration getCurrentConfig() { |
| return mCurrentConfig; |
| } |
| |
| public void getCurrentConfig(FolderConfiguration config) { |
| config.set(mCurrentConfig); |
| } |
| |
| public Rectangle getScreenBounds() { |
| // get the orientation from the current device config |
| ScreenOrientationQualifier qual = mCurrentConfig.getScreenOrientationQualifier(); |
| ScreenOrientation orientation = qual.getValue(); |
| |
| // get the device screen dimension |
| ScreenDimensionQualifier qual2 = mCurrentConfig.getScreenDimensionQualifier(); |
| int s1 = qual2.getValue1(); |
| int s2 = qual2.getValue2(); |
| |
| switch (orientation) { |
| default: |
| case PORTRAIT: |
| return new Rectangle(0, 0, s2, s1); |
| case LANDSCAPE: |
| return new Rectangle(0, 0, s1, s2); |
| case SQUARE: |
| return new Rectangle(0, 0, s1, s1); |
| } |
| } |
| |
| /** |
| * Updates the UI from values in the resources, such as languages, regions, themes, etc... |
| * This must be called from the UI thread. |
| */ |
| public void updateUIFromResources() { |
| if (mListener == null) { |
| return; // can't do anything w/o it. |
| } |
| |
| ProjectResources frameworkProject = mListener.getFrameworkResources(); |
| |
| mDisableUpdates = true; |
| |
| // Reset stuff |
| int selection = mThemeCombo.getSelectionIndex(); |
| mThemeCombo.removeAll(); |
| mPlatformThemeCount = 0; |
| |
| mLocale.removeAll(); |
| mLocaleList.clear(); |
| |
| SortedSet<String> languages = null; |
| ArrayList<String> themes = new ArrayList<String>(); |
| |
| // get the themes, and languages from the Framework. |
| if (frameworkProject != null) { |
| // get the configured resources for the framework |
| Map<String, Map<String, IResourceValue>> frameworResources = |
| mListener.getConfiguredFrameworkResources(); |
| |
| if (frameworResources != null) { |
| // get the styles. |
| Map<String, IResourceValue> styles = frameworResources.get( |
| ResourceType.STYLE.getName()); |
| |
| |
| // collect the themes out of all the styles. |
| for (IResourceValue value : styles.values()) { |
| String name = value.getName(); |
| if (name.startsWith("Theme.") || name.equals("Theme")) { |
| themes.add(value.getName()); |
| mPlatformThemeCount++; |
| } |
| } |
| |
| // sort them and add them to the combo |
| Collections.sort(themes); |
| |
| for (String theme : themes) { |
| mThemeCombo.add(theme); |
| } |
| |
| mPlatformThemeCount = themes.size(); |
| themes.clear(); |
| } |
| } |
| |
| // now get the themes and languages from the project. |
| ProjectResources project = mListener.getProjectResources(); |
| // in cases where the opened file is not linked to a project, this could be null. |
| if (project != null) { |
| // get the configured resources for the project |
| Map<String, Map<String, IResourceValue>> configuredProjectRes = |
| mListener.getConfiguredProjectResources(); |
| |
| if (configuredProjectRes != null) { |
| // get the styles. |
| Map<String, IResourceValue> styleMap = configuredProjectRes.get( |
| ResourceType.STYLE.getName()); |
| |
| if (styleMap != null) { |
| // collect the themes out of all the styles, ie styles that extend, |
| // directly or indirectly a platform theme. |
| for (IResourceValue value : styleMap.values()) { |
| if (isTheme(value, styleMap)) { |
| themes.add(value.getName()); |
| } |
| } |
| |
| // sort them and add them the to the combo. |
| if (mPlatformThemeCount > 0 && themes.size() > 0) { |
| mThemeCombo.add(THEME_SEPARATOR); |
| } |
| |
| Collections.sort(themes); |
| |
| for (String theme : themes) { |
| mThemeCombo.add(theme); |
| } |
| } |
| } |
| |
| // now get the languages from the project. |
| languages = project.getLanguages(); |
| } |
| |
| // add the languages to the Combo |
| mLocale.add("Default"); |
| mLocaleList.add(new ResourceQualifier[] { null, null }); |
| |
| if (project != null && languages != null && languages.size() > 0) { |
| for (String language : languages) { |
| // first the language alone |
| mLocale.add(language); |
| LanguageQualifier qual = new LanguageQualifier(language); |
| mLocaleList.add(new ResourceQualifier[] { qual, null }); |
| |
| // now find the matching regions and add them |
| SortedSet<String> regions = project.getRegions(language); |
| for (String region : regions) { |
| mLocale.add(String.format("%1$s_%2$s", language, region)); //$NON-NLS-1$ |
| RegionQualifier qual2 = new RegionQualifier(region); |
| mLocaleList.add(new ResourceQualifier[] { qual, qual2 }); |
| } |
| |
| } |
| } |
| |
| mDisableUpdates = false; |
| |
| // handle default selection of themes |
| if (mThemeCombo.getItemCount() > 0) { |
| mThemeCombo.setEnabled(true); |
| if (selection == -1) { |
| selection = 0; |
| } |
| |
| if (mThemeCombo.getItemCount() <= selection) { |
| mThemeCombo.select(0); |
| } else { |
| mThemeCombo.select(selection); |
| } |
| } else { |
| mThemeCombo.setEnabled(false); |
| } |
| |
| mThemeCombo.getParent().layout(); |
| } |
| |
| /** |
| * Returns the current theme, or null if the combo has no selection. |
| */ |
| public String getTheme() { |
| int themeIndex = mThemeCombo.getSelectionIndex(); |
| if (themeIndex != -1) { |
| return mThemeCombo.getItem(themeIndex); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Returns whether the current theme selection is a project theme. |
| * <p/>The returned value is meaningless if {@link #getTheme()} returns <code>null</code>. |
| * @return true for project theme, false for framework theme |
| */ |
| public boolean isProjectTheme() { |
| return mThemeCombo.getSelectionIndex() >= mPlatformThemeCount; |
| } |
| |
| |
| public void setEnabledCreate(boolean enabled) { |
| mCreateButton.setEnabled(enabled); |
| } |
| |
| /** |
| * Update the UI controls state with a given {@link FolderConfiguration}. |
| * <p/>If <var>force</var> is set to <code>true</code> the UI will be changed to exactly reflect |
| * <var>config</var>, otherwise, if a qualifier is not present in <var>config</var>, |
| * the UI control is not modified. However if the value in the control is not the default value, |
| * a warning icon is shown. |
| * @param config The {@link FolderConfiguration} to set. |
| * @param force Whether the UI should be changed to exactly match the received configuration. |
| */ |
| public void setConfiguration(FolderConfiguration config, boolean force) { |
| mDisableUpdates = true; // we do not want to trigger onXXXChange when setting new values in the widgets. |
| |
| // TODO: find a device that can display this particular config or create a custom one if needed. |
| |
| |
| // update the string showing the folder name |
| String current = config.toDisplayString(); |
| mCurrentLayoutLabel.setText(current != null ? current : "(Default)"); |
| |
| mDisableUpdates = false; |
| } |
| |
| private void onCountryCodeChange() { |
| // because mCountry triggers onCountryCodeChange at each modification, calling setText() |
| // will trigger notifications, and we don't want that. |
| if (mDisableUpdates == true) { |
| return; |
| } |
| |
| // update the current config |
| String value = mCountry.getText(); |
| |
| // empty string, means no qualifier. |
| if (value.length() == 0) { |
| mCurrentConfig.setCountryCodeQualifier(null); |
| } else { |
| try { |
| CountryCodeQualifier qualifier = CountryCodeQualifier.getQualifier( |
| CountryCodeQualifier.getFolderSegment(Integer.parseInt(value))); |
| if (qualifier != null) { |
| mCurrentConfig.setCountryCodeQualifier(qualifier); |
| } else { |
| // Failure! Looks like the value is wrong (for instance a one letter string). |
| // We do nothing in this case. |
| mCountryIcon.setImage(mErrorImage); |
| return; |
| } |
| } catch (NumberFormatException e) { |
| // Looks like the code is not a number. This should not happen since the text |
| // field has a VerifyListener that prevents it. |
| mCurrentConfig.setCountryCodeQualifier(null); |
| mCountryIcon.setImage(mErrorImage); |
| } |
| } |
| |
| if (mListener != null) { |
| mListener.onConfigurationChange(); |
| } |
| } |
| |
| private void onNetworkCodeChange() { |
| // because mNetwork triggers onNetworkCodeChange at each modification, calling setText() |
| // will trigger notifications, and we don't want that. |
| if (mDisableUpdates == true) { |
| return; |
| } |
| |
| // update the current config |
| String value = mNetwork.getText(); |
| |
| // empty string, means no qualifier. |
| if (value.length() == 0) { |
| mCurrentConfig.setNetworkCodeQualifier(null); |
| } else { |
| try { |
| NetworkCodeQualifier qualifier = NetworkCodeQualifier.getQualifier( |
| NetworkCodeQualifier.getFolderSegment(Integer.parseInt(value))); |
| if (qualifier != null) { |
| mCurrentConfig.setNetworkCodeQualifier(qualifier); |
| } else { |
| // Failure! Looks like the value is wrong (for instance a one letter string). |
| // We do nothing in this case. |
| mNetworkIcon.setImage(mErrorImage); |
| return; |
| } |
| } catch (NumberFormatException e) { |
| // Looks like the code is not a number. This should not happen since the text |
| // field has a VerifyListener that prevents it. |
| mCurrentConfig.setNetworkCodeQualifier(null); |
| mNetworkIcon.setImage(mErrorImage); |
| } |
| } |
| |
| if (mListener != null) { |
| mListener.onConfigurationChange(); |
| } |
| } |
| |
| /** |
| * Call back for language combo selection |
| */ |
| private void onLocaleChange() { |
| // because mLanguage triggers onLanguageChange at each modification, the filling |
| // of the combo with data will trigger notifications, and we don't want that. |
| if (mDisableUpdates == true) { |
| return; |
| } |
| |
| int localeIndex = mLocale.getSelectionIndex(); |
| ResourceQualifier[] localeQualifiers = mLocaleList.get(localeIndex); |
| |
| mCurrentConfig.setLanguageQualifier((LanguageQualifier)localeQualifiers[0]); // language |
| mCurrentConfig.setRegionQualifier((RegionQualifier)localeQualifiers[1]); // region |
| |
| if (mListener != null) { |
| mListener.onConfigurationChange(); |
| } |
| } |
| |
| private void onDeviceChange() { |
| |
| int deviceIndex = mDeviceList.getSelectionIndex(); |
| DeviceConfiguration device = mDevices[deviceIndex]; |
| |
| mDeviceConfigs.removeAll(); |
| |
| Set<String> configNames = device.getConfigs().keySet(); |
| for (String name : configNames) { |
| mDeviceConfigs.add(name); |
| } |
| |
| mDeviceConfigs.select(0); |
| if (configNames.size() == 1) { |
| mDeviceConfigs.setEnabled(false); |
| } |
| |
| onDeviceConfigChange(); |
| } |
| |
| private void onDeviceConfigChange() { |
| int deviceIndex = mDeviceList.getSelectionIndex(); |
| DeviceConfiguration device = mDevices[deviceIndex]; |
| |
| int configIndex = mDeviceConfigs.getSelectionIndex(); |
| String name = mDeviceConfigs.getItem(configIndex); |
| FolderConfiguration config = device.getConfigs().get(name); |
| |
| // get the current qualifiers from the current config |
| CountryCodeQualifier mcc = mCurrentConfig.getCountryCodeQualifier(); |
| NetworkCodeQualifier mnc = mCurrentConfig.getNetworkCodeQualifier(); |
| LanguageQualifier lang = mCurrentConfig.getLanguageQualifier(); |
| RegionQualifier region = mCurrentConfig.getRegionQualifier(); |
| VersionQualifier version = mCurrentConfig.getVersionQualifier(); |
| |
| // replace the config with the one from the device |
| mCurrentConfig.set(config); |
| |
| // and put back the rest of the qualifiers |
| mCurrentConfig.addQualifier(mcc); |
| mCurrentConfig.addQualifier(mnc); |
| mCurrentConfig.addQualifier(lang); |
| mCurrentConfig.addQualifier(region); |
| mCurrentConfig.addQualifier(version); |
| |
| if (mListener != null) { |
| mListener.onConfigurationChange(); |
| } |
| } |
| |
| private void onThemeChange() { |
| int themeIndex = mThemeCombo.getSelectionIndex(); |
| if (themeIndex != -1) { |
| String theme = mThemeCombo.getItem(themeIndex); |
| |
| if (theme.equals(THEME_SEPARATOR)) { |
| mThemeCombo.select(0); |
| } |
| |
| if (mListener != null) { |
| mListener.onThemeChange(); |
| } |
| } |
| } |
| |
| /** |
| * Creates a composite with no margin/spacing, and puts a {@link Label} in it with the matching |
| * icon. |
| * @param parent the parent to receive the composite |
| * @return the created {@link Label} object. |
| */ |
| private Label createControlComposite(Composite parent, boolean grab) { |
| GridLayout gl; |
| |
| Composite composite = new Composite(parent, SWT.NONE); |
| composite.setLayout(gl = new GridLayout(2, false)); |
| gl.marginHeight = gl.marginWidth = 0; |
| gl.horizontalSpacing = 0; |
| if (grab) { |
| composite.setLayoutData( |
| new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); |
| } |
| |
| // create the label |
| Label icon = new Label(composite, SWT.NONE); |
| icon.setImage(mMatchImage); |
| |
| return icon; |
| } |
| |
| /** |
| * Returns whether the given <var>style</var> is a theme. |
| * This is done by making sure the parent is a theme. |
| * @param value the style to check |
| * @param styleMap the map of styles for the current project. Key is the style name. |
| * @return True if the given <var>style</var> is a theme. |
| */ |
| private boolean isTheme(IResourceValue value, Map<String, IResourceValue> styleMap) { |
| if (value instanceof IStyleResourceValue) { |
| IStyleResourceValue style = (IStyleResourceValue)value; |
| |
| boolean frameworkStyle = false; |
| String parentStyle = style.getParentStyle(); |
| if (parentStyle == null) { |
| // if there is no specified parent style we look an implied one. |
| // For instance 'Theme.light' is implied child style of 'Theme', |
| // and 'Theme.light.fullscreen' is implied child style of 'Theme.light' |
| String name = style.getName(); |
| int index = name.lastIndexOf('.'); |
| if (index != -1) { |
| parentStyle = name.substring(0, index); |
| } |
| } else { |
| // remove the useless @ if it's there |
| if (parentStyle.startsWith("@")) { |
| parentStyle = parentStyle.substring(1); |
| } |
| |
| // check for framework identifier. |
| if (parentStyle.startsWith("android:")) { |
| frameworkStyle = true; |
| parentStyle = parentStyle.substring("android:".length()); |
| } |
| |
| // at this point we could have the format style/<name>. we want only the name |
| if (parentStyle.startsWith("style/")) { |
| parentStyle = parentStyle.substring("style/".length()); |
| } |
| } |
| |
| if (parentStyle != null) { |
| if (frameworkStyle) { |
| // if the parent is a framework style, it has to be 'Theme' or 'Theme.*' |
| return parentStyle.equals("Theme") || parentStyle.startsWith("Theme."); |
| } else { |
| // if it's a project style, we check this is a theme. |
| value = styleMap.get(parentStyle); |
| if (value != null) { |
| return isTheme(value, styleMap); |
| } |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| } |