From ffb7b7f81dda0fac6dd261112ba4dc5ec522cd56 Mon Sep 17 00:00:00 2001 From: Xavier Ducrohet Date: Wed, 19 Aug 2009 16:40:21 -0700 Subject: [PATCH] Refactor Config UI out of Layout Editor. --- .../layout/ConfigurationComposite.java | 1247 +++++++++++++++++ .../editors/layout/GraphicalLayoutEditor.java | 1212 +--------------- 2 files changed, 1307 insertions(+), 1152 deletions(-) create mode 100644 tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ConfigurationComposite.java diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ConfigurationComposite.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ConfigurationComposite.java new file mode 100644 index 000000000..67d64c7ec --- /dev/null +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ConfigurationComposite.java @@ -0,0 +1,1247 @@ +/* + * 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; + +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.KeyboardStateQualifier; +import com.android.ide.eclipse.adt.internal.resources.configurations.LanguageQualifier; +import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier; +import com.android.ide.eclipse.adt.internal.resources.configurations.NetworkCodeQualifier; +import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier; +import com.android.ide.eclipse.adt.internal.resources.configurations.RegionQualifier; +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.TextInputMethodQualifier; +import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier; +import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier.KeyboardState; +import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier.NavigationMethod; +import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier.Density; +import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier.ScreenOrientation; +import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier.TextInputMethod; +import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier.TouchScreenType; +import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources; +import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.DimensionVerifier; +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.HashSet; +import java.util.Map; +import java.util.Set; + +public class ConfigurationComposite extends Composite { + + private final static String THEME_SEPARATOR = "----------"; //$NON-NLS-1$ + + private Text mCountry; + private Text mNetwork; + private Combo mLanguage; + private Combo mRegion; + private Combo mOrientation; + private Combo mDensity; + private Combo mTouch; + private Combo mKeyboard; + private Combo mTextInput; + private Combo mNavigation; + private Text mSize1; + private Text mSize2; + private Combo mThemeCombo; + private Button mCreateButton; + + private Label mCountryIcon; + private Label mNetworkIcon; + private Label mLanguageIcon; + private Label mRegionIcon; + private Label mOrientationIcon; + private Label mDensityIcon; + private Label mTouchIcon; + private Label mKeyboardIcon; + private Label mTextInputIcon; + private Label mNavigationIcon; + private Label mSizeIcon; + + private Label mCurrentLayoutLabel; + + private Image mWarningImage; + 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 FolderConfiguration mCurrentConfig = new FolderConfiguration(); + private IConfigListener mListener; + + public interface IConfigListener { + void onConfigurationChange(); + void onThemeChange(); + void onCreate(); + + ProjectResources getProjectResources(); + ProjectResources getFrameworkResources(); + Map> getConfiguredProjectResources(); + Map> getConfiguredFrameworkResources(); + } + + public ConfigurationComposite(Composite parent, int style) { + super(parent, style); + + IconFactory factory = IconFactory.getInstance(); + mWarningImage = factory.getIcon("warning"); //$NON-NLS-1$ + 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("Lang"); + mLanguageIcon = createControlComposite(this, true /* grab_horizontal */); + mLanguage = new Combo(mLanguageIcon.getParent(), SWT.DROP_DOWN); + mLanguage.setLayoutData(new GridData( + GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); + mLanguage.addVerifyListener(new LanguageRegionVerifier()); + mLanguage.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + onLanguageChange(); + } + public void widgetSelected(SelectionEvent e) { + onLanguageChange(); + } + }); + mLanguage.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + onLanguageChange(); + } + }); + + new Label(this, SWT.NONE).setText("Region"); + mRegionIcon = createControlComposite(this, true /* grab_horizontal */); + mRegion = new Combo(mRegionIcon.getParent(), SWT.DROP_DOWN); + mRegion.setLayoutData(new GridData( + GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); + mRegion.addVerifyListener(new LanguageRegionVerifier()); + mRegion.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + onRegionChange(); + } + public void widgetSelected(SelectionEvent e) { + onRegionChange(); + } + }); + mRegion.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + onRegionChange(); + } + }); + + new Label(this, SWT.NONE).setText("Orient"); + mOrientationIcon = createControlComposite(this, true /* grab_horizontal */); + mOrientation = new Combo(mOrientationIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); + ScreenOrientation[] soValues = ScreenOrientation.values(); + mOrientation.add("(Default)"); + for (ScreenOrientation value : soValues) { + mOrientation.add(value.getDisplayValue()); + } + mOrientation.select(0); + mOrientation.setLayoutData(new GridData( + GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); + mOrientation.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + onOrientationChange(); + } + }); + + new Label(this, SWT.NONE).setText("Density"); + mDensityIcon = createControlComposite(this, true /* grab_horizontal */); + mDensity = new Combo(mDensityIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); + Density[] dValues = Density.values(); + mDensity.add("(Default)"); + for (Density value : dValues) { + mDensity.add(value.getDisplayValue()); + } + mDensity.select(0); + mDensity.setLayoutData(new GridData( + GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); + mDensity.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + onDensityChange(); + } + }); + + new Label(this, SWT.NONE).setText("Touch"); + mTouchIcon = createControlComposite(this, true /* grab_horizontal */); + mTouch = new Combo(mTouchIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); + TouchScreenType[] tstValues = TouchScreenType.values(); + mTouch.add("(Default)"); + for (TouchScreenType value : tstValues) { + mTouch.add(value.getDisplayValue()); + } + mTouch.select(0); + mTouch.setLayoutData(new GridData( + GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); + mTouch.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + onTouchChange(); + } + }); + + new Label(this, SWT.NONE).setText("Keybrd"); + mKeyboardIcon = createControlComposite(this, true /* grab_horizontal */); + mKeyboard = new Combo(mKeyboardIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); + KeyboardState[] ksValues = KeyboardState.values(); + mKeyboard.add("(Default)"); + for (KeyboardState value : ksValues) { + mKeyboard.add(value.getDisplayValue()); + } + mKeyboard.select(0); + mKeyboard.setLayoutData(new GridData( + GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); + mKeyboard.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + onKeyboardChange(); + } + }); + + new Label(this, SWT.NONE).setText("Input"); + mTextInputIcon = createControlComposite(this, true /* grab_horizontal */); + mTextInput = new Combo(mTextInputIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); + TextInputMethod[] timValues = TextInputMethod.values(); + mTextInput.add("(Default)"); + for (TextInputMethod value : timValues) { + mTextInput.add(value.getDisplayValue()); + } + mTextInput.select(0); + mTextInput.setLayoutData(new GridData( + GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); + mTextInput.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + onTextInputChange(); + } + }); + + new Label(this, SWT.NONE).setText("Nav"); + mNavigationIcon = createControlComposite(this, true /* grab_horizontal */); + mNavigation = new Combo(mNavigationIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); + NavigationMethod[] nValues = NavigationMethod.values(); + mNavigation.add("(Default)"); + for (NavigationMethod value : nValues) { + mNavigation.add(value.getDisplayValue()); + } + mNavigation.select(0); + mNavigation.setLayoutData(new GridData( + GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); + mNavigation.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + onNavigationChange(); + } + }); + + 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; + + new Label(labelParent, SWT.NONE).setText("Size"); + mSizeIcon = createControlComposite(labelParent, false); + Composite sizeParent = new Composite(mSizeIcon.getParent(), SWT.NONE); + sizeParent.setLayout(gl = new GridLayout(3, false)); + gl.marginWidth = gl.marginHeight = 0; + gl.horizontalSpacing = 0; + + mSize1 = new Text(sizeParent, SWT.BORDER); + mSize1.setLayoutData(gd = new GridData()); + gd.widthHint = 30; + new Label(sizeParent, SWT.NONE).setText("x"); + mSize2 = new Text(sizeParent, SWT.BORDER); + mSize2.setLayoutData(gd = new GridData()); + gd.widthHint = 30; + + DimensionVerifier verifier = new DimensionVerifier(); + mSize1.addVerifyListener(verifier); + mSize2.addVerifyListener(verifier); + + SelectionListener sl = new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + onSizeChange(); + } + public void widgetSelected(SelectionEvent e) { + onSizeChange(); + } + }; + + mSize1.addSelectionListener(sl); + mSize2.addSelectionListener(sl); + + ModifyListener sizeModifyListener = new ModifyListener() { + public void modifyText(ModifyEvent e) { + onSizeChange(); + } + }; + + mSize1.addModifyListener(sizeModifyListener); + mSize2.addModifyListener(sizeModifyListener); + + // 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(); + } + } + }); + + } + + public void setOnConfigurationChange(IConfigListener listener) { + mListener = listener; + } + + public void setConfig(FolderConfiguration config) { + mCurrentConfig.set(config); + } + + + public FolderConfiguration getCurrentConfig() { + return mCurrentConfig; + } + + public void getCurrentConfig(FolderConfiguration config) { + config.set(mCurrentConfig); + } + + public Rectangle getScreenBounds() { + ScreenOrientation orientation = null; + if (mOrientation.getSelectionIndex() == 0) { + orientation = ScreenOrientation.PORTRAIT; + } else { + orientation = ScreenOrientation.getByIndex( + mOrientation.getSelectionIndex() - 1); + } + + int s1, s2; + + // get the size from the UI controls. If it fails, revert to default values. + try { + s1 = Integer.parseInt(mSize1.getText().trim()); + } catch (NumberFormatException e) { + s1 = 480; + } + + try { + s2 = Integer.parseInt(mSize2.getText().trim()); + } catch (NumberFormatException e) { + s2 = 320; + } + + // make sure s1 is bigger than s2 + if (s1 < s2) { + int tmp = s1; + s1 = s2; + s2 = tmp; + } + + 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; + mLanguage.removeAll(); + + Set languages = new HashSet(); + ArrayList themes = new ArrayList(); + + // get the themes, and languages from the Framework. + if (frameworkProject != null) { + // get the configured resources for the framework + Map> frameworResources = + mListener.getConfiguredFrameworkResources(); + + if (frameworResources != null) { + // get the styles. + Map 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 languages from the framework. + Set frameworkLanguages = frameworkProject.getLanguages(); + if (frameworkLanguages != null) { + languages.addAll(frameworkLanguages); + } + } + + // 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> configuredProjectRes = + mListener.getConfiguredProjectResources(); + + if (configuredProjectRes != null) { + // get the styles. + Map 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. + Set projectLanguages = project.getLanguages(); + if (projectLanguages != null) { + languages.addAll(projectLanguages); + } + } + + // add the languages to the Combo + for (String language : languages) { + mLanguage.add(language); + } + + mDisableUpdates = false; + + // and update the Region UI based on the current language + updateRegionUi(); + + // 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(); + } + + + + /** + * Update the UI controls state with a given {@link FolderConfiguration}. + *

If force is set to true the UI will be changed to exactly reflect + * config, otherwise, if a qualifier is not present in config, + * 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. + */ + void setConfiguration(FolderConfiguration config, boolean force) { + mDisableUpdates = true; // we do not want to trigger onXXXChange when setting new values in the widgets. + + mCountryIcon.setImage(mMatchImage); + CountryCodeQualifier countryQualifier = config.getCountryCodeQualifier(); + if (countryQualifier != null) { + mCountry.setText(String.format("%1$d", countryQualifier.getCode())); + mCurrentConfig.setCountryCodeQualifier(countryQualifier); + } else if (force) { + mCountry.setText(""); //$NON-NLS-1$ + mCurrentConfig.setCountryCodeQualifier(null); + } else if (mCountry.getText().length() > 0) { + mCountryIcon.setImage(mWarningImage); + } + + mNetworkIcon.setImage(mMatchImage); + NetworkCodeQualifier networkQualifier = config.getNetworkCodeQualifier(); + if (networkQualifier != null) { + mNetwork.setText(String.format("%1$d", networkQualifier.getCode())); + mCurrentConfig.setNetworkCodeQualifier(networkQualifier); + } else if (force) { + mNetwork.setText(""); //$NON-NLS-1$ + mCurrentConfig.setNetworkCodeQualifier(null); + } else if (mNetwork.getText().length() > 0) { + mNetworkIcon.setImage(mWarningImage); + } + + mLanguageIcon.setImage(mMatchImage); + LanguageQualifier languageQualifier = config.getLanguageQualifier(); + if (languageQualifier != null) { + mLanguage.setText(languageQualifier.getValue()); + mCurrentConfig.setLanguageQualifier(languageQualifier); + } else if (force) { + mLanguage.setText(""); //$NON-NLS-1$ + mCurrentConfig.setLanguageQualifier(null); + } else if (mLanguage.getText().length() > 0) { + mLanguageIcon.setImage(mWarningImage); + } + + mRegionIcon.setImage(mMatchImage); + RegionQualifier regionQualifier = config.getRegionQualifier(); + if (regionQualifier != null) { + mRegion.setText(regionQualifier.getValue()); + mCurrentConfig.setRegionQualifier(regionQualifier); + } else if (force) { + mRegion.setText(""); //$NON-NLS-1$ + mCurrentConfig.setRegionQualifier(null); + } else if (mRegion.getText().length() > 0) { + mRegionIcon.setImage(mWarningImage); + } + + mOrientationIcon.setImage(mMatchImage); + ScreenOrientationQualifier orientationQualifier = config.getScreenOrientationQualifier(); + if (orientationQualifier != null) { + mOrientation.select( + ScreenOrientation.getIndex(orientationQualifier.getValue()) + 1); + mCurrentConfig.setScreenOrientationQualifier(orientationQualifier); + } else if (force) { + mOrientation.select(0); + mCurrentConfig.setScreenOrientationQualifier(null); + } else if (mOrientation.getSelectionIndex() != 0) { + mOrientationIcon.setImage(mWarningImage); + } + + mDensityIcon.setImage(mMatchImage); + PixelDensityQualifier densityQualifier = config.getPixelDensityQualifier(); + if (densityQualifier != null) { + mDensity.select( + Density.getIndex(densityQualifier.getValue()) + 1); + mCurrentConfig.setPixelDensityQualifier(densityQualifier); + } else if (force) { + mOrientation.select(0); + mCurrentConfig.setPixelDensityQualifier(null); + } else if (mDensity.getSelectionIndex() != 0) { + mDensityIcon.setImage(mWarningImage); + } + + mTouchIcon.setImage(mMatchImage); + TouchScreenQualifier touchQualifier = config.getTouchTypeQualifier(); + if (touchQualifier != null) { + mTouch.select(TouchScreenType.getIndex(touchQualifier.getValue()) + 1); + mCurrentConfig.setTouchTypeQualifier(touchQualifier); + } else if (force) { + mTouch.select(0); + mCurrentConfig.setTouchTypeQualifier(null); + } else if (mTouch.getSelectionIndex() != 0) { + mTouchIcon.setImage(mWarningImage); + } + + mKeyboardIcon.setImage(mMatchImage); + KeyboardStateQualifier keyboardQualifier = config.getKeyboardStateQualifier(); + if (keyboardQualifier != null) { + mKeyboard.select(KeyboardState.getIndex(keyboardQualifier.getValue()) + 1); + mCurrentConfig.setKeyboardStateQualifier(keyboardQualifier); + } else if (force) { + mKeyboard.select(0); + mCurrentConfig.setKeyboardStateQualifier(null); + } else if (mKeyboard.getSelectionIndex() != 0) { + mKeyboardIcon.setImage(mWarningImage); + } + + mTextInputIcon.setImage(mMatchImage); + TextInputMethodQualifier inputQualifier = config.getTextInputMethodQualifier(); + if (inputQualifier != null) { + mTextInput.select(TextInputMethod.getIndex(inputQualifier.getValue()) + 1); + mCurrentConfig.setTextInputMethodQualifier(inputQualifier); + } else if (force) { + mTextInput.select(0); + mCurrentConfig.setTextInputMethodQualifier(null); + } else if (mTextInput.getSelectionIndex() != 0) { + mTextInputIcon.setImage(mWarningImage); + } + + mNavigationIcon.setImage(mMatchImage); + NavigationMethodQualifier navigationQualifiter = config.getNavigationMethodQualifier(); + if (navigationQualifiter != null) { + mNavigation.select( + NavigationMethod.getIndex(navigationQualifiter.getValue()) + 1); + mCurrentConfig.setNavigationMethodQualifier(navigationQualifiter); + } else if (force) { + mNavigation.select(0); + mCurrentConfig.setNavigationMethodQualifier(null); + } else if (mNavigation.getSelectionIndex() != 0) { + mNavigationIcon.setImage(mWarningImage); + } + + mSizeIcon.setImage(mMatchImage); + ScreenDimensionQualifier sizeQualifier = config.getScreenDimensionQualifier(); + if (sizeQualifier != null) { + mSize1.setText(String.format("%1$d", sizeQualifier.getValue1())); + mSize2.setText(String.format("%1$d", sizeQualifier.getValue2())); + mCurrentConfig.setScreenDimensionQualifier(sizeQualifier); + } else if (force) { + mSize1.setText(""); //$NON-NLS-1$ + mSize2.setText(""); //$NON-NLS-1$ + mCurrentConfig.setScreenDimensionQualifier(null); + } else if (mSize1.getText().length() > 0 && mSize2.getText().length() > 0) { + mSizeIcon.setImage(mWarningImage); + } + + // update the string showing the folder name + String current = config.toDisplayString(); + mCurrentLayoutLabel.setText(current != null ? current : "(Default)"); + + mDisableUpdates = false; + } + + /** + * Displays an error icon in front of all the non-null qualifiers. + */ + void displayConfigError() { + mCountryIcon.setImage(mMatchImage); + CountryCodeQualifier countryQualifier = mCurrentConfig.getCountryCodeQualifier(); + if (countryQualifier != null) { + mCountryIcon.setImage(mErrorImage); + } + + mNetworkIcon.setImage(mMatchImage); + NetworkCodeQualifier networkQualifier = mCurrentConfig.getNetworkCodeQualifier(); + if (networkQualifier != null) { + mNetworkIcon.setImage(mErrorImage); + } + + mLanguageIcon.setImage(mMatchImage); + LanguageQualifier languageQualifier = mCurrentConfig.getLanguageQualifier(); + if (languageQualifier != null) { + mLanguageIcon.setImage(mErrorImage); + } + + mRegionIcon.setImage(mMatchImage); + RegionQualifier regionQualifier = mCurrentConfig.getRegionQualifier(); + if (regionQualifier != null) { + mRegionIcon.setImage(mErrorImage); + } + + mOrientationIcon.setImage(mMatchImage); + ScreenOrientationQualifier orientationQualifier = + mCurrentConfig.getScreenOrientationQualifier(); + if (orientationQualifier != null) { + mOrientationIcon.setImage(mErrorImage); + } + + mDensityIcon.setImage(mMatchImage); + PixelDensityQualifier densityQualifier = mCurrentConfig.getPixelDensityQualifier(); + if (densityQualifier != null) { + mDensityIcon.setImage(mErrorImage); + } + + mTouchIcon.setImage(mMatchImage); + TouchScreenQualifier touchQualifier = mCurrentConfig.getTouchTypeQualifier(); + if (touchQualifier != null) { + mTouchIcon.setImage(mErrorImage); + } + + mKeyboardIcon.setImage(mMatchImage); + KeyboardStateQualifier keyboardQualifier = mCurrentConfig.getKeyboardStateQualifier(); + if (keyboardQualifier != null) { + mKeyboardIcon.setImage(mErrorImage); + } + + mTextInputIcon.setImage(mMatchImage); + TextInputMethodQualifier inputQualifier = mCurrentConfig.getTextInputMethodQualifier(); + if (inputQualifier != null) { + mTextInputIcon.setImage(mErrorImage); + } + + mNavigationIcon.setImage(mMatchImage); + NavigationMethodQualifier navigationQualifiter = + mCurrentConfig.getNavigationMethodQualifier(); + if (navigationQualifiter != null) { + mNavigationIcon.setImage(mErrorImage); + } + + mSizeIcon.setImage(mMatchImage); + ScreenDimensionQualifier sizeQualifier = mCurrentConfig.getScreenDimensionQualifier(); + if (sizeQualifier != null) { + mSizeIcon.setImage(mErrorImage); + } + + // update the string showing the folder name + String current = mCurrentConfig.toDisplayString(); + mCurrentLayoutLabel.setText(current != null ? current : "(Default)"); + } + + + + 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 onLanguageChange() { + // 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; + } + + // update the current config + String value = mLanguage.getText(); + + updateRegionUi(); + + // empty string, means no qualifier. + if (value.length() == 0) { + mCurrentConfig.setLanguageQualifier(null); + } else { + LanguageQualifier qualifier = null; + String segment = LanguageQualifier.getFolderSegment(value); + if (segment != null) { + qualifier = LanguageQualifier.getQualifier(segment); + } + + if (qualifier != null) { + mCurrentConfig.setLanguageQualifier(qualifier); + } else { + // Failure! Looks like the value is wrong (for instance a one letter string). + mCurrentConfig.setLanguageQualifier(null); + mLanguageIcon.setImage(mErrorImage); + } + } + + if (mListener != null) { + mListener.onConfigurationChange(); + } + } + + private void onRegionChange() { + // because mRegion triggers onRegionChange at each modification, the filling + // of the combo with data will trigger notifications, and we don't want that. + if (mDisableUpdates == true) { + return; + } + + // update the current config + String value = mRegion.getText(); + + // empty string, means no qualifier. + if (value.length() == 0) { + mCurrentConfig.setRegionQualifier(null); + } else { + RegionQualifier qualifier = null; + String segment = RegionQualifier.getFolderSegment(value); + if (segment != null) { + qualifier = RegionQualifier.getQualifier(segment); + } + + if (qualifier != null) { + mCurrentConfig.setRegionQualifier(qualifier); + } else { + // Failure! Looks like the value is wrong (for instance a one letter string). + mCurrentConfig.setRegionQualifier(null); + mRegionIcon.setImage(mErrorImage); + } + } + + if (mListener != null) { + mListener.onConfigurationChange(); + } + } + + private void onOrientationChange() { + // update the current config + int index = mOrientation.getSelectionIndex(); + if (index != 0) { + mCurrentConfig.setScreenOrientationQualifier(new ScreenOrientationQualifier( + ScreenOrientation.getByIndex(index-1))); + } else { + mCurrentConfig.setScreenOrientationQualifier(null); + } + + if (mListener != null) { + mListener.onConfigurationChange(); + } + } + + private void onDensityChange() { + int index = mDensity.getSelectionIndex(); + if (index != 0) { + mCurrentConfig.setPixelDensityQualifier((new PixelDensityQualifier( + Density.getByIndex(index-1)))); + } else { + mCurrentConfig.setPixelDensityQualifier(null); + } + + if (mListener != null) { + mListener.onConfigurationChange(); + } + } + + private void onTouchChange() { + // update the current config + int index = mTouch.getSelectionIndex(); + if (index != 0) { + mCurrentConfig.setTouchTypeQualifier(new TouchScreenQualifier( + TouchScreenType.getByIndex(index-1))); + } else { + mCurrentConfig.setTouchTypeQualifier(null); + } + + if (mListener != null) { + mListener.onConfigurationChange(); + } + } + + private void onKeyboardChange() { + // update the current config + int index = mKeyboard.getSelectionIndex(); + if (index != 0) { + mCurrentConfig.setKeyboardStateQualifier(new KeyboardStateQualifier( + KeyboardState.getByIndex(index-1))); + } else { + mCurrentConfig.setKeyboardStateQualifier(null); + } + + if (mListener != null) { + mListener.onConfigurationChange(); + } + } + + private void onTextInputChange() { + // update the current config + int index = mTextInput.getSelectionIndex(); + if (index != 0) { + mCurrentConfig.setTextInputMethodQualifier(new TextInputMethodQualifier( + TextInputMethod.getByIndex(index-1))); + } else { + mCurrentConfig.setTextInputMethodQualifier(null); + } + + if (mListener != null) { + mListener.onConfigurationChange(); + } + } + + private void onNavigationChange() { + // update the current config + int index = mNavigation.getSelectionIndex(); + if (index != 0) { + mCurrentConfig.setNavigationMethodQualifier(new NavigationMethodQualifier( + NavigationMethod.getByIndex(index-1))); + } else { + mCurrentConfig.setNavigationMethodQualifier(null); + } + + if (mListener != null) { + mListener.onConfigurationChange(); + } + } + + private void onSizeChange() { + // because mSize1 and mSize2 trigger onSizeChange at each modification, calling setText() + // will trigger notifications, and we don't want that. + if (mDisableUpdates == true) { + return; + } + + // update the current config + String size1 = mSize1.getText(); + String size2 = mSize2.getText(); + + // if only one of the strings is empty, do nothing + if ((size1.length() == 0) ^ (size2.length() == 0)) { + mSizeIcon.setImage(mErrorImage); + return; + } else if (size1.length() == 0 && size2.length() == 0) { + // both sizes are empty: remove the qualifier. + mCurrentConfig.setScreenDimensionQualifier(null); + } else { + ScreenDimensionQualifier qualifier = ScreenDimensionQualifier.getQualifier(size1, + size2); + + if (qualifier != null) { + mCurrentConfig.setScreenDimensionQualifier(qualifier); + } else { + // Failure! Looks like the value is wrong. + // we do nothing in this case. + return; + } + } + + 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; + } + + /** + * Update the Region UI widget based on the current language selection + * @param projectResources the project resources or {@code null}. + * @param frameworkResources the framework resource or {@code null} + */ + private void updateRegionUi() { + if (mListener == null) { + return; + } + + ProjectResources projectResources = mListener.getProjectResources(); + ProjectResources frameworkResources = mListener.getFrameworkResources(); + + String currentLanguage = mLanguage.getText(); + + Set set = null; + + if (projectResources != null) { + set = projectResources.getRegions(currentLanguage); + } + + if (frameworkResources != null) { + if (set != null) { + Set set2 = frameworkResources.getRegions(currentLanguage); + set.addAll(set2); + } else { + set = frameworkResources.getRegions(currentLanguage); + } + } + + if (set != null) { + mDisableUpdates = true; + + mRegion.removeAll(); + for (String region : set) { + mRegion.add(region); + } + + mDisableUpdates = false; + } + } + + + /** + * Returns whether the given style 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 style is a theme. + */ + private boolean isTheme(IResourceValue value, Map 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/. we want only the name + if (parentStyle.startsWith("style/")) { + parentStyle = parentStyle.substring("style/".length()); + } + } + + 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; + } +} diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/GraphicalLayoutEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/GraphicalLayoutEditor.java index 225d5bda1..e2d91218f 100644 --- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/GraphicalLayoutEditor.java +++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/GraphicalLayoutEditor.java @@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.internal.editors.layout; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.editors.IconFactory; +import com.android.ide.eclipse.adt.internal.editors.layout.ConfigurationComposite.IConfigListener; import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor.UiEditorActions; import com.android.ide.eclipse.adt.internal.editors.layout.LayoutReloadMonitor.ILayoutReloadListener; import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor; @@ -142,9 +143,8 @@ import java.util.Set; * To understand Drag'n'drop: http://www.eclipse.org/articles/Article-Workbench-DND/drag_drop.html */ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor - implements ILayoutReloadListener { + implements ILayoutReloadListener, IConfigListener { - private final static String THEME_SEPARATOR = "----------"; //$NON-NLS-1$ /** Reference to the layout editor */ private final LayoutEditor mLayoutEditor; @@ -154,43 +154,10 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor private Clipboard mClipboard; private Composite mParent; + private ConfigurationComposite mConfigComposite; + private PaletteRoot mPaletteRoot; - private Text mCountry; - private Text mNetwork; - private Combo mLanguage; - private Combo mRegion; - private Combo mOrientation; - private Combo mDensity; - private Combo mTouch; - private Combo mKeyboard; - private Combo mTextInput; - private Combo mNavigation; - private Text mSize1; - private Text mSize2; - private Combo mThemeCombo; - private Button mCreateButton; - - private Label mCountryIcon; - private Label mNetworkIcon; - private Label mLanguageIcon; - private Label mRegionIcon; - private Label mOrientationIcon; - private Label mDensityIcon; - private Label mTouchIcon; - private Label mKeyboardIcon; - private Label mTextInputIcon; - private Label mNavigationIcon; - private Label mSizeIcon; - - private Label mCurrentLayoutLabel; - - private Image mWarningImage; - private Image mMatchImage; - private Image mErrorImage; - - /** The {@link FolderConfiguration} representing the state of the UI controls */ - private FolderConfiguration mCurrentConfig = new FolderConfiguration(); /** The {@link FolderConfiguration} being edited. */ private FolderConfiguration mEditedConfig; @@ -202,7 +169,6 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor private boolean mNeedsXmlReload = false; private boolean mNeedsRecompute = false; private int mPlatformThemeCount = 0; - private boolean mDisableUpdates = false; /** Listener to update the root node if the target of the file is changed because of a * SDK location change or a project target change */ @@ -217,9 +183,7 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor // because the SDK changed we must reset the configured framework resource. mConfiguredFrameworkRes = null; - updateUIFromResources(); - - mThemeCombo.getParent().layout(); + mConfigComposite.updateUIFromResources(); // updateUiFromFramework will reset language/region combo, so we must call // setConfiguration after, or the settext on language/region will be lost. @@ -247,21 +211,16 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor private final Runnable mUiUpdateFromResourcesRunnable = new Runnable() { public void run() { - updateUIFromResources(); - mThemeCombo.getParent().layout(); + mConfigComposite.updateUIFromResources(); } }; + public GraphicalLayoutEditor(LayoutEditor layoutEditor) { mLayoutEditor = layoutEditor; setEditDomain(new DefaultEditDomain(this)); setPartName("Layout"); - IconFactory factory = IconFactory.getInstance(); - mWarningImage = factory.getIcon("warning"); //$NON-NLS-1$ - mMatchImage = factory.getIcon("match"); //$NON-NLS-1$ - mErrorImage = factory.getIcon("error"); //$NON-NLS-1$ - AdtPlugin.getDefault().addTargetListener(mTargetListener); } @@ -273,7 +232,6 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor public void createPartControl(Composite parent) { mParent = parent; GridLayout gl; - GridData gd; mClipboard = new Clipboard(parent.getDisplay()); @@ -281,286 +239,7 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor gl.marginHeight = gl.marginWidth = 0; // create the top part for the configuration control - int cols = 10; - - Composite topParent = new Composite(parent, SWT.NONE); - topParent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - topParent.setLayout(gl = new GridLayout(cols, false)); - - new Label(topParent, SWT.NONE).setText("MCC"); - mCountryIcon = createControlComposite(topParent, 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(topParent, SWT.NONE).setText("MNC"); - mNetworkIcon = createControlComposite(topParent, 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(topParent, SWT.NONE).setText("Lang"); - mLanguageIcon = createControlComposite(topParent, true /* grab_horizontal */); - mLanguage = new Combo(mLanguageIcon.getParent(), SWT.DROP_DOWN); - mLanguage.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mLanguage.addVerifyListener(new LanguageRegionVerifier()); - mLanguage.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onLanguageChange(); - } - public void widgetSelected(SelectionEvent e) { - onLanguageChange(); - } - }); - mLanguage.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onLanguageChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Region"); - mRegionIcon = createControlComposite(topParent, true /* grab_horizontal */); - mRegion = new Combo(mRegionIcon.getParent(), SWT.DROP_DOWN); - mRegion.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mRegion.addVerifyListener(new LanguageRegionVerifier()); - mRegion.addSelectionListener(new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onRegionChange(); - } - public void widgetSelected(SelectionEvent e) { - onRegionChange(); - } - }); - mRegion.addModifyListener(new ModifyListener() { - public void modifyText(ModifyEvent e) { - onRegionChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Orient"); - mOrientationIcon = createControlComposite(topParent, true /* grab_horizontal */); - mOrientation = new Combo(mOrientationIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); - ScreenOrientation[] soValues = ScreenOrientation.values(); - mOrientation.add("(Default)"); - for (ScreenOrientation value : soValues) { - mOrientation.add(value.getDisplayValue()); - } - mOrientation.select(0); - mOrientation.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mOrientation.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onOrientationChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Density"); - mDensityIcon = createControlComposite(topParent, true /* grab_horizontal */); - mDensity = new Combo(mDensityIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); - Density[] dValues = Density.values(); - mDensity.add("(Default)"); - for (Density value : dValues) { - mDensity.add(value.getDisplayValue()); - } - mDensity.select(0); - mDensity.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mDensity.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onDensityChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Touch"); - mTouchIcon = createControlComposite(topParent, true /* grab_horizontal */); - mTouch = new Combo(mTouchIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); - TouchScreenType[] tstValues = TouchScreenType.values(); - mTouch.add("(Default)"); - for (TouchScreenType value : tstValues) { - mTouch.add(value.getDisplayValue()); - } - mTouch.select(0); - mTouch.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mTouch.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onTouchChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Keybrd"); - mKeyboardIcon = createControlComposite(topParent, true /* grab_horizontal */); - mKeyboard = new Combo(mKeyboardIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); - KeyboardState[] ksValues = KeyboardState.values(); - mKeyboard.add("(Default)"); - for (KeyboardState value : ksValues) { - mKeyboard.add(value.getDisplayValue()); - } - mKeyboard.select(0); - mKeyboard.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mKeyboard.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onKeyboardChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Input"); - mTextInputIcon = createControlComposite(topParent, true /* grab_horizontal */); - mTextInput = new Combo(mTextInputIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); - TextInputMethod[] timValues = TextInputMethod.values(); - mTextInput.add("(Default)"); - for (TextInputMethod value : timValues) { - mTextInput.add(value.getDisplayValue()); - } - mTextInput.select(0); - mTextInput.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mTextInput.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onTextInputChange(); - } - }); - - new Label(topParent, SWT.NONE).setText("Nav"); - mNavigationIcon = createControlComposite(topParent, true /* grab_horizontal */); - mNavigation = new Combo(mNavigationIcon.getParent(), SWT.DROP_DOWN | SWT.READ_ONLY); - NavigationMethod[] nValues = NavigationMethod.values(); - mNavigation.add("(Default)"); - for (NavigationMethod value : nValues) { - mNavigation.add(value.getDisplayValue()); - } - mNavigation.select(0); - mNavigation.setLayoutData(new GridData( - GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL)); - mNavigation.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - onNavigationChange(); - } - }); - - Composite labelParent = new Composite(topParent, 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; - - new Label(labelParent, SWT.NONE).setText("Size"); - mSizeIcon = createControlComposite(labelParent, false); - Composite sizeParent = new Composite(mSizeIcon.getParent(), SWT.NONE); - sizeParent.setLayout(gl = new GridLayout(3, false)); - gl.marginWidth = gl.marginHeight = 0; - gl.horizontalSpacing = 0; - - mSize1 = new Text(sizeParent, SWT.BORDER); - mSize1.setLayoutData(gd = new GridData()); - gd.widthHint = 30; - new Label(sizeParent, SWT.NONE).setText("x"); - mSize2 = new Text(sizeParent, SWT.BORDER); - mSize2.setLayoutData(gd = new GridData()); - gd.widthHint = 30; - - DimensionVerifier verifier = new DimensionVerifier(); - mSize1.addVerifyListener(verifier); - mSize2.addVerifyListener(verifier); - - SelectionListener sl = new SelectionListener() { - public void widgetDefaultSelected(SelectionEvent e) { - onSizeChange(); - } - public void widgetSelected(SelectionEvent e) { - onSizeChange(); - } - }; - - mSize1.addSelectionListener(sl); - mSize2.addSelectionListener(sl); - - ModifyListener sizeModifyListener = new ModifyListener() { - public void modifyText(ModifyEvent e) { - onSizeChange(); - } - }; - - mSize1.addModifyListener(sizeModifyListener); - mSize2.addModifyListener(sizeModifyListener); - - // 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) { - LayoutCreatorDialog dialog = new LayoutCreatorDialog(mCreateButton.getShell(), - mEditedFile.getName(), - Sdk.getCurrent().getTarget(mEditedFile.getProject()), mCurrentConfig); - if (dialog.open() == Dialog.OK) { - final FolderConfiguration config = new FolderConfiguration(); - dialog.getConfiguration(config); - - createAlternateLayout(config); - } - } - }); + mConfigComposite = new ConfigurationComposite(parent, SWT.NONE); // create a new composite that will contain the standard editor controls. Composite editorParent = new Composite(parent, SWT.NONE); @@ -689,7 +368,7 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor FileEditorInput fileInput = (FileEditorInput)input; mEditedFile = fileInput.getFile(); - updateUIFromResources(); + mConfigComposite.updateUIFromResources(); LayoutReloadMonitor.getMonitor().addListener(mEditedFile.getProject(), this); } else { @@ -873,49 +552,12 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor setConfiguration(configuration, true /*force*/); // enable the create button if the current and edited config are not equals - mCreateButton.setEnabled(mEditedConfig.equals(mCurrentConfig) == false); + mCreateButton.setEnabled( + mEditedConfig.equals(mConfigComposite.getCurrentConfig()) == false); } public Rectangle getBounds() { - ScreenOrientation orientation = null; - if (mOrientation.getSelectionIndex() == 0) { - orientation = ScreenOrientation.PORTRAIT; - } else { - orientation = ScreenOrientation.getByIndex( - mOrientation.getSelectionIndex() - 1); - } - - int s1, s2; - - // get the size from the UI controls. If it fails, revert to default values. - try { - s1 = Integer.parseInt(mSize1.getText().trim()); - } catch (NumberFormatException e) { - s1 = 480; - } - - try { - s2 = Integer.parseInt(mSize2.getText().trim()); - } catch (NumberFormatException e) { - s2 = 320; - } - - // make sure s1 is bigger than s2 - if (s1 < s2) { - int tmp = s1; - s1 = s2; - s2 = tmp; - } - - 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); - } + return mConfigComposite.getScreenBounds(); } /** @@ -1080,231 +722,13 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor * @param force Whether the UI should be changed to exactly match the received configuration. */ void setConfiguration(FolderConfiguration config, boolean force) { - mDisableUpdates = true; // we do not want to trigger onXXXChange when setting new values in the widgets. - mEditedConfig = config; mConfiguredFrameworkRes = mConfiguredProjectRes = null; - mCountryIcon.setImage(mMatchImage); - CountryCodeQualifier countryQualifier = config.getCountryCodeQualifier(); - if (countryQualifier != null) { - mCountry.setText(String.format("%1$d", countryQualifier.getCode())); - mCurrentConfig.setCountryCodeQualifier(countryQualifier); - } else if (force) { - mCountry.setText(""); //$NON-NLS-1$ - mCurrentConfig.setCountryCodeQualifier(null); - } else if (mCountry.getText().length() > 0) { - mCountryIcon.setImage(mWarningImage); - } + mConfigComposite.setConfiguration(config, force); - mNetworkIcon.setImage(mMatchImage); - NetworkCodeQualifier networkQualifier = config.getNetworkCodeQualifier(); - if (networkQualifier != null) { - mNetwork.setText(String.format("%1$d", networkQualifier.getCode())); - mCurrentConfig.setNetworkCodeQualifier(networkQualifier); - } else if (force) { - mNetwork.setText(""); //$NON-NLS-1$ - mCurrentConfig.setNetworkCodeQualifier(null); - } else if (mNetwork.getText().length() > 0) { - mNetworkIcon.setImage(mWarningImage); - } - - mLanguageIcon.setImage(mMatchImage); - LanguageQualifier languageQualifier = config.getLanguageQualifier(); - if (languageQualifier != null) { - mLanguage.setText(languageQualifier.getValue()); - mCurrentConfig.setLanguageQualifier(languageQualifier); - } else if (force) { - mLanguage.setText(""); //$NON-NLS-1$ - mCurrentConfig.setLanguageQualifier(null); - } else if (mLanguage.getText().length() > 0) { - mLanguageIcon.setImage(mWarningImage); - } - - mRegionIcon.setImage(mMatchImage); - RegionQualifier regionQualifier = config.getRegionQualifier(); - if (regionQualifier != null) { - mRegion.setText(regionQualifier.getValue()); - mCurrentConfig.setRegionQualifier(regionQualifier); - } else if (force) { - mRegion.setText(""); //$NON-NLS-1$ - mCurrentConfig.setRegionQualifier(null); - } else if (mRegion.getText().length() > 0) { - mRegionIcon.setImage(mWarningImage); - } - - mOrientationIcon.setImage(mMatchImage); - ScreenOrientationQualifier orientationQualifier = config.getScreenOrientationQualifier(); - if (orientationQualifier != null) { - mOrientation.select( - ScreenOrientation.getIndex(orientationQualifier.getValue()) + 1); - mCurrentConfig.setScreenOrientationQualifier(orientationQualifier); - } else if (force) { - mOrientation.select(0); - mCurrentConfig.setScreenOrientationQualifier(null); - } else if (mOrientation.getSelectionIndex() != 0) { - mOrientationIcon.setImage(mWarningImage); - } - - mDensityIcon.setImage(mMatchImage); - PixelDensityQualifier densityQualifier = config.getPixelDensityQualifier(); - if (densityQualifier != null) { - mDensity.select( - Density.getIndex(densityQualifier.getValue()) + 1); - mCurrentConfig.setPixelDensityQualifier(densityQualifier); - } else if (force) { - mOrientation.select(0); - mCurrentConfig.setPixelDensityQualifier(null); - } else if (mDensity.getSelectionIndex() != 0) { - mDensityIcon.setImage(mWarningImage); - } - - mTouchIcon.setImage(mMatchImage); - TouchScreenQualifier touchQualifier = config.getTouchTypeQualifier(); - if (touchQualifier != null) { - mTouch.select(TouchScreenType.getIndex(touchQualifier.getValue()) + 1); - mCurrentConfig.setTouchTypeQualifier(touchQualifier); - } else if (force) { - mTouch.select(0); - mCurrentConfig.setTouchTypeQualifier(null); - } else if (mTouch.getSelectionIndex() != 0) { - mTouchIcon.setImage(mWarningImage); - } - - mKeyboardIcon.setImage(mMatchImage); - KeyboardStateQualifier keyboardQualifier = config.getKeyboardStateQualifier(); - if (keyboardQualifier != null) { - mKeyboard.select(KeyboardState.getIndex(keyboardQualifier.getValue()) + 1); - mCurrentConfig.setKeyboardStateQualifier(keyboardQualifier); - } else if (force) { - mKeyboard.select(0); - mCurrentConfig.setKeyboardStateQualifier(null); - } else if (mKeyboard.getSelectionIndex() != 0) { - mKeyboardIcon.setImage(mWarningImage); - } - - mTextInputIcon.setImage(mMatchImage); - TextInputMethodQualifier inputQualifier = config.getTextInputMethodQualifier(); - if (inputQualifier != null) { - mTextInput.select(TextInputMethod.getIndex(inputQualifier.getValue()) + 1); - mCurrentConfig.setTextInputMethodQualifier(inputQualifier); - } else if (force) { - mTextInput.select(0); - mCurrentConfig.setTextInputMethodQualifier(null); - } else if (mTextInput.getSelectionIndex() != 0) { - mTextInputIcon.setImage(mWarningImage); - } - - mNavigationIcon.setImage(mMatchImage); - NavigationMethodQualifier navigationQualifiter = config.getNavigationMethodQualifier(); - if (navigationQualifiter != null) { - mNavigation.select( - NavigationMethod.getIndex(navigationQualifiter.getValue()) + 1); - mCurrentConfig.setNavigationMethodQualifier(navigationQualifiter); - } else if (force) { - mNavigation.select(0); - mCurrentConfig.setNavigationMethodQualifier(null); - } else if (mNavigation.getSelectionIndex() != 0) { - mNavigationIcon.setImage(mWarningImage); - } - - mSizeIcon.setImage(mMatchImage); - ScreenDimensionQualifier sizeQualifier = config.getScreenDimensionQualifier(); - if (sizeQualifier != null) { - mSize1.setText(String.format("%1$d", sizeQualifier.getValue1())); - mSize2.setText(String.format("%1$d", sizeQualifier.getValue2())); - mCurrentConfig.setScreenDimensionQualifier(sizeQualifier); - } else if (force) { - mSize1.setText(""); //$NON-NLS-1$ - mSize2.setText(""); //$NON-NLS-1$ - mCurrentConfig.setScreenDimensionQualifier(null); - } else if (mSize1.getText().length() > 0 && mSize2.getText().length() > 0) { - mSizeIcon.setImage(mWarningImage); - } - - // update the string showing the folder name - String current = config.toDisplayString(); - mCurrentLayoutLabel.setText(current != null ? current : "(Default)"); - - mDisableUpdates = false; } - /** - * Displays an error icon in front of all the non-null qualifiers. - */ - void displayConfigError() { - mCountryIcon.setImage(mMatchImage); - CountryCodeQualifier countryQualifier = mCurrentConfig.getCountryCodeQualifier(); - if (countryQualifier != null) { - mCountryIcon.setImage(mErrorImage); - } - - mNetworkIcon.setImage(mMatchImage); - NetworkCodeQualifier networkQualifier = mCurrentConfig.getNetworkCodeQualifier(); - if (networkQualifier != null) { - mNetworkIcon.setImage(mErrorImage); - } - - mLanguageIcon.setImage(mMatchImage); - LanguageQualifier languageQualifier = mCurrentConfig.getLanguageQualifier(); - if (languageQualifier != null) { - mLanguageIcon.setImage(mErrorImage); - } - - mRegionIcon.setImage(mMatchImage); - RegionQualifier regionQualifier = mCurrentConfig.getRegionQualifier(); - if (regionQualifier != null) { - mRegionIcon.setImage(mErrorImage); - } - - mOrientationIcon.setImage(mMatchImage); - ScreenOrientationQualifier orientationQualifier = - mCurrentConfig.getScreenOrientationQualifier(); - if (orientationQualifier != null) { - mOrientationIcon.setImage(mErrorImage); - } - - mDensityIcon.setImage(mMatchImage); - PixelDensityQualifier densityQualifier = mCurrentConfig.getPixelDensityQualifier(); - if (densityQualifier != null) { - mDensityIcon.setImage(mErrorImage); - } - - mTouchIcon.setImage(mMatchImage); - TouchScreenQualifier touchQualifier = mCurrentConfig.getTouchTypeQualifier(); - if (touchQualifier != null) { - mTouchIcon.setImage(mErrorImage); - } - - mKeyboardIcon.setImage(mMatchImage); - KeyboardStateQualifier keyboardQualifier = mCurrentConfig.getKeyboardStateQualifier(); - if (keyboardQualifier != null) { - mKeyboardIcon.setImage(mErrorImage); - } - - mTextInputIcon.setImage(mMatchImage); - TextInputMethodQualifier inputQualifier = mCurrentConfig.getTextInputMethodQualifier(); - if (inputQualifier != null) { - mTextInputIcon.setImage(mErrorImage); - } - - mNavigationIcon.setImage(mMatchImage); - NavigationMethodQualifier navigationQualifiter = - mCurrentConfig.getNavigationMethodQualifier(); - if (navigationQualifiter != null) { - mNavigationIcon.setImage(mErrorImage); - } - - mSizeIcon.setImage(mMatchImage); - ScreenDimensionQualifier sizeQualifier = mCurrentConfig.getScreenDimensionQualifier(); - if (sizeQualifier != null) { - mSizeIcon.setImage(mErrorImage); - } - - // update the string showing the folder name - String current = mCurrentConfig.toDisplayString(); - mCurrentLayoutLabel.setText(current != null ? current : "(Default)"); - } @Override UiDocumentNode getModel() { @@ -1316,275 +740,13 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor PaletteFactory.createPaletteRoot(mPaletteRoot, mLayoutEditor.getTargetData()); } - 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); - } - } - - // look for a file to open/create - 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); - } - } - - // look for a file to open/create - onConfigurationChange(); - } - - /** - * Call back for language combo selection - */ - private void onLanguageChange() { - // 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; - } - - // update the current config - String value = mLanguage.getText(); - - updateRegionUi(null /* projectResources */, null /* frameworkResources */); - - // empty string, means no qualifier. - if (value.length() == 0) { - mCurrentConfig.setLanguageQualifier(null); - } else { - LanguageQualifier qualifier = null; - String segment = LanguageQualifier.getFolderSegment(value); - if (segment != null) { - qualifier = LanguageQualifier.getQualifier(segment); - } - - if (qualifier != null) { - mCurrentConfig.setLanguageQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong (for instance a one letter string). - mCurrentConfig.setLanguageQualifier(null); - mLanguageIcon.setImage(mErrorImage); - } - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onRegionChange() { - // because mRegion triggers onRegionChange at each modification, the filling - // of the combo with data will trigger notifications, and we don't want that. - if (mDisableUpdates == true) { - return; - } - - // update the current config - String value = mRegion.getText(); - - // empty string, means no qualifier. - if (value.length() == 0) { - mCurrentConfig.setRegionQualifier(null); - } else { - RegionQualifier qualifier = null; - String segment = RegionQualifier.getFolderSegment(value); - if (segment != null) { - qualifier = RegionQualifier.getQualifier(segment); - } - - if (qualifier != null) { - mCurrentConfig.setRegionQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong (for instance a one letter string). - mCurrentConfig.setRegionQualifier(null); - mRegionIcon.setImage(mErrorImage); - } - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onOrientationChange() { - // update the current config - int index = mOrientation.getSelectionIndex(); - if (index != 0) { - mCurrentConfig.setScreenOrientationQualifier(new ScreenOrientationQualifier( - ScreenOrientation.getByIndex(index-1))); - } else { - mCurrentConfig.setScreenOrientationQualifier(null); - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onDensityChange() { - int index = mDensity.getSelectionIndex(); - if (index != 0) { - mCurrentConfig.setPixelDensityQualifier((new PixelDensityQualifier( - Density.getByIndex(index-1)))); - } else { - mCurrentConfig.setPixelDensityQualifier(null); - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onTouchChange() { - // update the current config - int index = mTouch.getSelectionIndex(); - if (index != 0) { - mCurrentConfig.setTouchTypeQualifier(new TouchScreenQualifier( - TouchScreenType.getByIndex(index-1))); - } else { - mCurrentConfig.setTouchTypeQualifier(null); - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onKeyboardChange() { - // update the current config - int index = mKeyboard.getSelectionIndex(); - if (index != 0) { - mCurrentConfig.setKeyboardStateQualifier(new KeyboardStateQualifier( - KeyboardState.getByIndex(index-1))); - } else { - mCurrentConfig.setKeyboardStateQualifier(null); - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onTextInputChange() { - // update the current config - int index = mTextInput.getSelectionIndex(); - if (index != 0) { - mCurrentConfig.setTextInputMethodQualifier(new TextInputMethodQualifier( - TextInputMethod.getByIndex(index-1))); - } else { - mCurrentConfig.setTextInputMethodQualifier(null); - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onNavigationChange() { - // update the current config - int index = mNavigation.getSelectionIndex(); - if (index != 0) { - mCurrentConfig.setNavigationMethodQualifier(new NavigationMethodQualifier( - NavigationMethod.getByIndex(index-1))); - } else { - mCurrentConfig.setNavigationMethodQualifier(null); - } - - // look for a file to open/create - onConfigurationChange(); - } - - private void onSizeChange() { - // because mSize1 and mSize2 trigger onSizeChange at each modification, calling setText() - // will trigger notifications, and we don't want that. - if (mDisableUpdates == true) { - return; - } - - // update the current config - String size1 = mSize1.getText(); - String size2 = mSize2.getText(); - - // if only one of the strings is empty, do nothing - if ((size1.length() == 0) ^ (size2.length() == 0)) { - mSizeIcon.setImage(mErrorImage); - return; - } else if (size1.length() == 0 && size2.length() == 0) { - // both sizes are empty: remove the qualifier. - mCurrentConfig.setScreenDimensionQualifier(null); - } else { - ScreenDimensionQualifier qualifier = ScreenDimensionQualifier.getQualifier(size1, - size2); - - if (qualifier != null) { - mCurrentConfig.setScreenDimensionQualifier(qualifier); - } else { - // Failure! Looks like the value is wrong. - // we do nothing in this case. - return; - } - } - - // look for a file to open/create - onConfigurationChange(); - } /** * Looks for a file matching the new {@link FolderConfiguration} and attempts to open it. *

If there is no match, notify the user. */ - private void onConfigurationChange() { + public void onConfigurationChange() { mConfiguredFrameworkRes = mConfiguredProjectRes = null; if (mEditedFile == null || mEditedConfig == null) { @@ -1600,7 +762,7 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor if (resources != null) { match = resources.getMatchingFile(mEditedFile.getName(), ResourceFolderType.LAYOUT, - mCurrentConfig); + mConfigComposite.getCurrentConfig()); } if (match != null) { @@ -1623,14 +785,15 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor setConfiguration(mEditedConfig, false /*force*/); // enable the create button if the current and edited config are not equals - mCreateButton.setEnabled(mEditedConfig.equals(mCurrentConfig) == false); + mCreateButton.setEnabled( + mEditedConfig.equals(mConfigComposite.getCurrentConfig()) == false); // Even though the layout doesn't change, the config changed, and referenced // resources need to be updated. recomputeLayout(); } else { // update the configuration icons with the new edited config. - displayConfigError(); + mConfigComposite.displayConfigError(); // enable the Create button mCreateButton.setEnabled(true); @@ -1646,42 +809,21 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor } } - private void onThemeChange() { - int themeIndex = mThemeCombo.getSelectionIndex(); - if (themeIndex != -1) { - String theme = mThemeCombo.getItem(themeIndex); - - if (theme.equals(THEME_SEPARATOR)) { - mThemeCombo.select(0); - } - - recomputeLayout(); - } + public void onThemeChange() { + recomputeLayout(); } - /** - * 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; + public void onCreate() { + LayoutCreatorDialog dialog = new LayoutCreatorDialog(mParent.getShell(), + mEditedFile.getName(), + Sdk.getCurrent().getTarget(mEditedFile.getProject()), + mConfigComposite.getCurrentConfig()); + if (dialog.open() == Dialog.OK) { + final FolderConfiguration config = new FolderConfiguration(); + dialog.getConfiguration(config); - 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)); + createAlternateLayout(config); } - - // create the label - Label icon = new Label(composite, SWT.NONE); - icon.setImage(mMatchImage); - - return icon; } /** @@ -1765,7 +907,8 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor projectRes.loadAll(); // get the project resource values based on the current config - mConfiguredProjectRes = projectRes.getConfiguredResources(mCurrentConfig); + mConfiguredProjectRes = projectRes.getConfiguredResources( + mConfigComposite.getCurrentConfig()); } // get the framework resources @@ -1985,244 +1128,7 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor // nothing to be done here for now. } - /** - * Updates the UI from values in the resources, such as languages, regions, themes, etc... - * This must be called from the UI thread. - */ - private void updateUIFromResources() { - - ResourceManager manager = ResourceManager.getInstance(); - - ProjectResources frameworkProject = getFrameworkResources(); - - mDisableUpdates = true; - - // Reset stuff - int selection = mThemeCombo.getSelectionIndex(); - mThemeCombo.removeAll(); - mPlatformThemeCount = 0; - mLanguage.removeAll(); - - Set languages = new HashSet(); - ArrayList themes = new ArrayList(); - - // get the themes, and languages from the Framework. - if (frameworkProject != null) { - // get the configured resources for the framework - Map> frameworResources = - getConfiguredFrameworkResources(); - - if (frameworResources != null) { - // get the styles. - Map 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 languages from the framework. - Set frameworkLanguages = frameworkProject.getLanguages(); - if (frameworkLanguages != null) { - languages.addAll(frameworkLanguages); - } - } - - // now get the themes and languages from the project. - ProjectResources project = null; - if (mEditedFile != null) { - project = manager.getProjectResources(mEditedFile.getProject()); - - // 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 - if (mConfiguredProjectRes == null) { - // make sure they are loaded - project.loadAll(); - - // get the project resource values based on the current config - mConfiguredProjectRes = project.getConfiguredResources(mCurrentConfig); - } - - if (mConfiguredProjectRes != null) { - // get the styles. - Map styleMap = mConfiguredProjectRes.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. - Set projectLanguages = project.getLanguages(); - if (projectLanguages != null) { - languages.addAll(projectLanguages); - } - } - } - - // add the languages to the Combo - for (String language : languages) { - mLanguage.add(language); - } - - mDisableUpdates = false; - - // and update the Region UI based on the current language - updateRegionUi(project, frameworkProject); - - // 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); - } - } - - /** - * Returns whether the given style 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 style is a theme. - */ - private boolean isTheme(IResourceValue value, Map 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/. we want only the name - if (parentStyle.startsWith("style/")) { - parentStyle = parentStyle.substring("style/".length()); - } - } - - 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; - } - - /** - * Update the Region UI widget based on the current language selection - * @param projectResources the project resources or {@code null}. - * @param frameworkResources the framework resource or {@code null} - */ - private void updateRegionUi(ProjectResources projectResources, - ProjectResources frameworkResources) { - if (projectResources == null && mEditedFile != null) { - projectResources = ResourceManager.getInstance().getProjectResources( - mEditedFile.getProject()); - } - - if (frameworkResources == null) { - frameworkResources = getFrameworkResources(); - } - - String currentLanguage = mLanguage.getText(); - - Set set = null; - - if (projectResources != null) { - set = projectResources.getRegions(currentLanguage); - } - - if (frameworkResources != null) { - if (set != null) { - Set set2 = frameworkResources.getRegions(currentLanguage); - set.addAll(set2); - } else { - set = frameworkResources.getRegions(currentLanguage); - } - } - - if (set != null) { - mDisableUpdates = true; - - mRegion.removeAll(); - for (String region : set) { - mRegion.add(region); - } - - mDisableUpdates = false; - } - } - - private Map> getConfiguredFrameworkResources() { + public Map> getConfiguredFrameworkResources() { if (mConfiguredFrameworkRes == null) { ProjectResources frameworkRes = getFrameworkResources(); @@ -2231,14 +1137,38 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor } // get the framework resource values based on the current config - mConfiguredFrameworkRes = frameworkRes.getConfiguredResources(mCurrentConfig); + mConfiguredFrameworkRes = frameworkRes.getConfiguredResources( + mConfigComposite.getCurrentConfig()); } return mConfiguredFrameworkRes; } /** - * Creates a new layout file from the specificed {@link FolderConfiguration}. + * Returns a {@link ProjectResources} for the framework resources. + * @return the framework resources or null if not found. + */ + public ProjectResources getFrameworkResources() { + if (mEditedFile != null) { + Sdk currentSdk = Sdk.getCurrent(); + if (currentSdk != null) { + IAndroidTarget target = currentSdk.getTarget(mEditedFile.getProject()); + + if (target != null) { + AndroidTargetData data = currentSdk.getTargetData(target); + + if (data != null) { + return data.getFrameworkResources(); + } + } + } + } + + return null; + } + + /** + * Creates a new layout file from the specified {@link FolderConfiguration}. */ private void createAlternateLayout(final FolderConfiguration config) { new Job("Create Alternate Resource") { @@ -2295,7 +1225,7 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor // to trigger the edit of the new file. res.refreshLocal(IResource.DEPTH_INFINITE, new IProgressMonitor() { public void done() { - mCurrentConfig.set(config); + mConfigComposite.setConfig(config); mParent.getDisplay().asyncExec(new Runnable() { public void run() { onConfigurationChange(); @@ -2357,29 +1287,6 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor }.schedule(); } - /** - * Returns a {@link ProjectResources} for the framework resources. - * @return the framework resources or null if not found. - */ - private ProjectResources getFrameworkResources() { - if (mEditedFile != null) { - Sdk currentSdk = Sdk.getCurrent(); - if (currentSdk != null) { - IAndroidTarget target = currentSdk.getTarget(mEditedFile.getProject()); - - if (target != null) { - AndroidTargetData data = currentSdk.getTargetData(target); - - if (data != null) { - return data.getFrameworkResources(); - } - } - } - } - - return null; - } - /** * Computes a layout by calling the correct computeLayout method of ILayoutBridge based on * the implementation API level. @@ -2423,4 +1330,5 @@ public class GraphicalLayoutEditor extends AbstractGraphicalLayoutEditor mLogger); } } + }