/* * 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.ui; import com.android.ide.eclipse.editors.resources.configurations.CountryCodeQualifier; import com.android.ide.eclipse.editors.resources.configurations.FolderConfiguration; import com.android.ide.eclipse.editors.resources.configurations.KeyboardStateQualifier; import com.android.ide.eclipse.editors.resources.configurations.LanguageQualifier; import com.android.ide.eclipse.editors.resources.configurations.NavigationMethodQualifier; import com.android.ide.eclipse.editors.resources.configurations.NetworkCodeQualifier; import com.android.ide.eclipse.editors.resources.configurations.PixelDensityQualifier; import com.android.ide.eclipse.editors.resources.configurations.RegionQualifier; import com.android.ide.eclipse.editors.resources.configurations.ResourceQualifier; import com.android.ide.eclipse.editors.resources.configurations.ScreenDimensionQualifier; import com.android.ide.eclipse.editors.resources.configurations.ScreenOrientationQualifier; import com.android.ide.eclipse.editors.resources.configurations.TextInputMethodQualifier; import com.android.ide.eclipse.editors.resources.configurations.TouchScreenQualifier; import com.android.ide.eclipse.editors.resources.configurations.KeyboardStateQualifier.KeyboardState; import com.android.ide.eclipse.editors.resources.configurations.NavigationMethodQualifier.NavigationMethod; import com.android.ide.eclipse.editors.resources.configurations.ScreenOrientationQualifier.ScreenOrientation; import com.android.ide.eclipse.editors.resources.configurations.TextInputMethodQualifier.TextInputMethod; import com.android.ide.eclipse.editors.resources.configurations.TouchScreenQualifier.TouchScreenType; import com.android.ide.eclipse.editors.resources.manager.ResourceManager; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; 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.events.VerifyEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; 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.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; import java.util.HashMap; /** * Custom UI widget to let user build a Folder configuration. * <p/> * To use this, instantiate somewhere in the UI and then: * <ul> * <li>Use {@link #setConfiguration(String)} or {@link #setConfiguration(FolderConfiguration)}. * <li>Retrieve the configuration using {@link #getConfiguration(FolderConfiguration)}. * </ul> */ public class ConfigurationSelector extends Composite { public static final int WIDTH_HINT = 600; public static final int HEIGHT_HINT = 250; private Runnable mOnChangeListener; private TableViewer mFullTableViewer; private TableViewer mSelectionTableViewer; private Button mAddButton; private Button mRemoveButton; private StackLayout mStackLayout; private boolean mOnRefresh = false; private final FolderConfiguration mBaseConfiguration = new FolderConfiguration(); private final FolderConfiguration mSelectedConfiguration = new FolderConfiguration(); private final HashMap<Class<? extends ResourceQualifier>, QualifierEditBase> mUiMap = new HashMap<Class<? extends ResourceQualifier>, QualifierEditBase>(); private Composite mQualifierEditParent; /** * Basic of {@link VerifyListener} to only accept digits. */ private static class DigitVerifier implements VerifyListener { public void verifyText(VerifyEvent e) { // check for digit only. for (int i = 0 ; i < e.text.length(); i++) { char letter = e.text.charAt(i); if (letter < '0' || letter > '9') { e.doit = false; return; } } } } /** * Implementation of {@link VerifyListener} for Country Code qualifiers. */ public static class MobileCodeVerifier extends DigitVerifier { @Override public void verifyText(VerifyEvent e) { super.verifyText(e); // basic tests passed? if (e.doit) { // check the max 3 digits. if (e.text.length() - e.end + e.start + ((Text)e.getSource()).getText().length() > 3) { e.doit = false; } } } } /** * Implementation of {@link VerifyListener} for the Language and Region qualifiers. */ public static class LanguageRegionVerifier implements VerifyListener { public void verifyText(VerifyEvent e) { // check for length if (e.text.length() - e.end + e.start + ((Combo)e.getSource()).getText().length() > 2) { e.doit = false; return; } // check for lower case only. for (int i = 0 ; i < e.text.length(); i++) { char letter = e.text.charAt(i); if ((letter < 'a' || letter > 'z') && (letter < 'A' || letter > 'Z')) { e.doit = false; return; } } } } /** * Implementation of {@link VerifyListener} for the Pixel Density qualifier. */ public static class DensityVerifier extends DigitVerifier { } /** * Implementation of {@link VerifyListener} for the Screen Dimension qualifier. */ public static class DimensionVerifier extends DigitVerifier { } /** * Enum for the state of the configuration being created. */ public enum ConfigurationState { OK, INVALID_CONFIG, REGION_WITHOUT_LANGUAGE; } public ConfigurationSelector(Composite parent) { super(parent, SWT.NONE); mBaseConfiguration.createDefault(); GridLayout gl = new GridLayout(4, false); gl.marginWidth = gl.marginHeight = 0; setLayout(gl); // first column is the first table final Table fullTable = new Table(this, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER); fullTable.setLayoutData(new GridData(GridData.FILL_BOTH)); fullTable.setHeaderVisible(true); fullTable.setLinesVisible(true); // create the column final TableColumn fullTableColumn = new TableColumn(fullTable, SWT.LEFT); // set the header fullTableColumn.setText("Available Qualifiers"); fullTable.addControlListener(new ControlAdapter() { @Override public void controlResized(ControlEvent e) { Rectangle r = fullTable.getClientArea(); fullTableColumn.setWidth(r.width); } }); mFullTableViewer = new TableViewer(fullTable); mFullTableViewer.setContentProvider(new QualifierContentProvider()); mFullTableViewer.setLabelProvider(new QualifierLabelProvider( false /* showQualifierValue */)); mFullTableViewer.setInput(mBaseConfiguration); mFullTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { ISelection selection = event.getSelection(); if (selection instanceof IStructuredSelection) { IStructuredSelection structSelection = (IStructuredSelection)selection; Object first = structSelection.getFirstElement(); if (first instanceof ResourceQualifier) { mAddButton.setEnabled(true); return; } } mAddButton.setEnabled(false); } }); // 2nd column is the left/right arrow button Composite buttonComposite = new Composite(this, SWT.NONE); gl = new GridLayout(1, false); gl.marginWidth = gl.marginHeight = 0; buttonComposite.setLayout(gl); buttonComposite.setLayoutData(new GridData(GridData.FILL_VERTICAL)); new Composite(buttonComposite, SWT.NONE); mAddButton = new Button(buttonComposite, SWT.BORDER | SWT.PUSH); mAddButton.setText("->"); mAddButton.setEnabled(false); mAddButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { IStructuredSelection selection = (IStructuredSelection)mFullTableViewer.getSelection(); Object first = selection.getFirstElement(); if (first instanceof ResourceQualifier) { ResourceQualifier qualifier = (ResourceQualifier)first; mBaseConfiguration.removeQualifier(qualifier); mSelectedConfiguration.addQualifier(qualifier); mFullTableViewer.refresh(); mSelectionTableViewer.refresh(); mSelectionTableViewer.setSelection(new StructuredSelection(qualifier), true); onChange(false /* keepSelection */); } } }); mRemoveButton = new Button(buttonComposite, SWT.BORDER | SWT.PUSH); mRemoveButton.setText("<-"); mRemoveButton.setEnabled(false); mRemoveButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { IStructuredSelection selection = (IStructuredSelection)mSelectionTableViewer.getSelection(); Object first = selection.getFirstElement(); if (first instanceof ResourceQualifier) { ResourceQualifier qualifier = (ResourceQualifier)first; mSelectedConfiguration.removeQualifier(qualifier); mBaseConfiguration.addQualifier(qualifier); mFullTableViewer.refresh(); mSelectionTableViewer.refresh(); onChange(false /* keepSelection */); } } }); // 3rd column is the selected config table final Table selectionTable = new Table(this, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER); selectionTable.setLayoutData(new GridData(GridData.FILL_BOTH)); selectionTable.setHeaderVisible(true); selectionTable.setLinesVisible(true); // create the column final TableColumn selectionTableColumn = new TableColumn(selectionTable, SWT.LEFT); // set the header selectionTableColumn.setText("Chosen Qualifiers"); selectionTable.addControlListener(new ControlAdapter() { @Override public void controlResized(ControlEvent e) { Rectangle r = selectionTable.getClientArea(); selectionTableColumn.setWidth(r.width); } }); mSelectionTableViewer = new TableViewer(selectionTable); mSelectionTableViewer.setContentProvider(new QualifierContentProvider()); mSelectionTableViewer.setLabelProvider(new QualifierLabelProvider( true /* showQualifierValue */)); mSelectionTableViewer.setInput(mSelectedConfiguration); mSelectionTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { // ignore selection changes during resfreshes in some cases. if (mOnRefresh) { return; } ISelection selection = event.getSelection(); if (selection instanceof IStructuredSelection) { IStructuredSelection structSelection = (IStructuredSelection)selection; if (structSelection.isEmpty() == false) { Object first = structSelection.getFirstElement(); if (first instanceof ResourceQualifier) { mRemoveButton.setEnabled(true); QualifierEditBase composite = mUiMap.get(first.getClass()); if (composite != null) { composite.setQualifier((ResourceQualifier)first); } mStackLayout.topControl = composite; mQualifierEditParent.layout(); return; } } else { mStackLayout.topControl = null; mQualifierEditParent.layout(); } } mRemoveButton.setEnabled(false); } }); // 4th column is the detail of the selected qualifier mQualifierEditParent = new Composite(this, SWT.NONE); mQualifierEditParent.setLayout(mStackLayout = new StackLayout()); mQualifierEditParent.setLayoutData(new GridData(GridData.FILL_VERTICAL)); // create the UI for all the qualifiers, and associate them to the ResourceQualifer class. mUiMap.put(CountryCodeQualifier.class, new MCCEdit(mQualifierEditParent)); mUiMap.put(NetworkCodeQualifier.class, new MNCEdit(mQualifierEditParent)); mUiMap.put(LanguageQualifier.class, new LanguageEdit(mQualifierEditParent)); mUiMap.put(RegionQualifier.class, new RegionEdit(mQualifierEditParent)); mUiMap.put(ScreenOrientationQualifier.class, new OrientationEdit(mQualifierEditParent)); mUiMap.put(PixelDensityQualifier.class, new PixelDensityEdit(mQualifierEditParent)); mUiMap.put(TouchScreenQualifier.class, new TouchEdit(mQualifierEditParent)); mUiMap.put(KeyboardStateQualifier.class, new KeyboardEdit(mQualifierEditParent)); mUiMap.put(TextInputMethodQualifier.class, new TextInputEdit(mQualifierEditParent)); mUiMap.put(NavigationMethodQualifier.class, new NavigationEdit(mQualifierEditParent)); mUiMap.put(ScreenDimensionQualifier.class, new ScreenDimensionEdit(mQualifierEditParent)); } /** * Sets a listener to be notified when the configuration changes. * @param listener A {@link Runnable} whose <code>run()</code> method is called when the * configuration is changed. The method is called from the UI thread. */ public void setOnChangeListener(Runnable listener) { mOnChangeListener = listener; } /** * Initialize the UI with a given {@link FolderConfiguration}. This must * be called from the UI thread. * @param config The configuration. */ public void setConfiguration(FolderConfiguration config) { mSelectedConfiguration.set(config); mSelectionTableViewer.refresh(); // create the base config, which is the default config minus the qualifiers // in SelectedConfiguration mBaseConfiguration.substract(mSelectedConfiguration); mFullTableViewer.refresh(); } /** * Initialize the UI with the configuration represented by a resource folder name. * This must be called from the UI thread. * * @param folderSegments the segments of the folder name, * split using {@link FolderConfiguration#QUALIFIER_SEP}. * @return true if success, or false if the folder name is not a valid name. */ public boolean setConfiguration(String[] folderSegments) { FolderConfiguration config = ResourceManager.getInstance().getConfig(folderSegments); if (config == null) { return false; } setConfiguration(config); return true; } /** * Initialize the UI with the configuration represented by a resource folder name. * This must be called from the UI thread. * @param folderName the name of the folder. * @return true if success, or false if the folder name is not a valid name. */ public boolean setConfiguration(String folderName) { // split the name of the folder in segments. String[] folderSegments = folderName.split(FolderConfiguration.QUALIFIER_SEP); return setConfiguration(folderSegments); } /** * Gets the configuration as setup by the widget. * @param config the {@link FolderConfiguration} object to be filled with the information * from the UI. */ public void getConfiguration(FolderConfiguration config) { config.set(mSelectedConfiguration); } /** * Returns the state of the configuration being edited/created. */ public ConfigurationState getState() { if (mSelectedConfiguration.getInvalidQualifier() != null) { return ConfigurationState.INVALID_CONFIG; } if (mSelectedConfiguration.checkRegion() == false) { return ConfigurationState.REGION_WITHOUT_LANGUAGE; } return ConfigurationState.OK; } /** * Returns the first invalid qualifier of the configuration being edited/created, * or <code>null<code> if they are all valid (or if none exists). * <p/>If {@link #getState()} return {@link ConfigurationState#INVALID_CONFIG} then this will * not return <code>null</code>. */ public ResourceQualifier getInvalidQualifier() { return mSelectedConfiguration.getInvalidQualifier(); } /** * Handle changes in the configuration. * @param keepSelection if <code>true</code> attemps to avoid triggering selection change in * {@link #mSelectedConfiguration}. */ private void onChange(boolean keepSelection) { ISelection selection = null; if (keepSelection) { mOnRefresh = true; selection = mSelectionTableViewer.getSelection(); } mSelectionTableViewer.refresh(true); if (keepSelection) { mSelectionTableViewer.setSelection(selection); mOnRefresh = false; } if (mOnChangeListener != null) { mOnChangeListener.run(); } } /** * Content provider around a {@link FolderConfiguration}. */ private static class QualifierContentProvider implements IStructuredContentProvider { private FolderConfiguration mInput; public QualifierContentProvider() { } public void dispose() { // pass } public Object[] getElements(Object inputElement) { return mInput.getQualifiers(); } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { mInput = null; if (newInput instanceof FolderConfiguration) { mInput = (FolderConfiguration)newInput; } } } /** * Label provider for {@link ResourceQualifier} objects. */ private static class QualifierLabelProvider implements ITableLabelProvider { private final boolean mShowQualifierValue; public QualifierLabelProvider(boolean showQualifierValue) { mShowQualifierValue = showQualifierValue; } public String getColumnText(Object element, int columnIndex) { // only one column, so we can ignore columnIndex if (element instanceof ResourceQualifier) { if (mShowQualifierValue) { String value = ((ResourceQualifier)element).getStringValue(); if (value.length() == 0) { return String.format("%1$s (?)", ((ResourceQualifier)element).getShortName()); } else { return value; } } else { return ((ResourceQualifier)element).getShortName(); } } return null; } public Image getColumnImage(Object element, int columnIndex) { // only one column, so we can ignore columnIndex if (element instanceof ResourceQualifier) { return ((ResourceQualifier)element).getIcon(); } return null; } public void addListener(ILabelProviderListener listener) { // pass } public void dispose() { // pass } public boolean isLabelProperty(Object element, String property) { // pass return false; } public void removeListener(ILabelProviderListener listener) { // pass } } /** * Base class for Edit widget for {@link ResourceQualifier}. */ private abstract static class QualifierEditBase extends Composite { public QualifierEditBase(Composite parent, String title) { super(parent, SWT.NONE); setLayout(new GridLayout(1, false)); new Label(this, SWT.NONE).setText(title); } public abstract void setQualifier(ResourceQualifier qualifier); } /** * Edit widget for {@link CountryCodeQualifier}. */ private class MCCEdit extends QualifierEditBase { private Text mText; public MCCEdit(Composite parent) { super(parent, CountryCodeQualifier.NAME); mText = new Text(this, SWT.BORDER); mText.addVerifyListener(new MobileCodeVerifier()); mText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { onTextChange(); } }); mText.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { onTextChange(); } }); new Label(this, SWT.NONE).setText("(3 digit code)"); } private void onTextChange() { String value = mText.getText(); if (value.length() == 0) { // empty string, means a qualifier with no value. // Since the qualifier classes are immutable, and we don't want to // remove the qualifier from the configuration, we create a new default one. mSelectedConfiguration.setCountryCodeQualifier(new CountryCodeQualifier()); } else { try { CountryCodeQualifier qualifier = CountryCodeQualifier.getQualifier( CountryCodeQualifier.getFolderSegment(Integer.parseInt(value))); if (qualifier != null) { mSelectedConfiguration.setCountryCodeQualifier(qualifier); } else { // Failure! Looks like the value is wrong // (for instance not exactly 3 digits). mSelectedConfiguration.setCountryCodeQualifier(new CountryCodeQualifier()); } } catch (NumberFormatException nfe) { // Looks like the code is not a number. This should not happen since the text // field has a VerifyListener that prevents it. mSelectedConfiguration.setCountryCodeQualifier(new CountryCodeQualifier()); } } // notify of change onChange(true /* keepSelection */); } @Override public void setQualifier(ResourceQualifier qualifier) { CountryCodeQualifier q = (CountryCodeQualifier)qualifier; mText.setText(Integer.toString(q.getCode())); } } /** * Edit widget for {@link NetworkCodeQualifier}. */ private class MNCEdit extends QualifierEditBase { private Text mText; public MNCEdit(Composite parent) { super(parent, NetworkCodeQualifier.NAME); mText = new Text(this, SWT.BORDER); mText.addVerifyListener(new MobileCodeVerifier()); mText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { onTextChange(); } }); mText.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { onTextChange(); } }); new Label(this, SWT.NONE).setText("(1-3 digit code)"); } private void onTextChange() { String value = mText.getText(); if (value.length() == 0) { // empty string, means a qualifier with no value. // Since the qualifier classes are immutable, and we don't want to // remove the qualifier from the configuration, we create a new default one. mSelectedConfiguration.setNetworkCodeQualifier(new NetworkCodeQualifier()); } else { try { NetworkCodeQualifier qualifier = NetworkCodeQualifier.getQualifier( NetworkCodeQualifier.getFolderSegment(Integer.parseInt(value))); if (qualifier != null) { mSelectedConfiguration.setNetworkCodeQualifier(qualifier); } else { // Failure! Looks like the value is wrong // (for instance not exactly 3 digits). mSelectedConfiguration.setNetworkCodeQualifier(new NetworkCodeQualifier()); } } catch (NumberFormatException nfe) { // Looks like the code is not a number. This should not happen since the text // field has a VerifyListener that prevents it. mSelectedConfiguration.setNetworkCodeQualifier(new NetworkCodeQualifier()); } } // notify of change onChange(true /* keepSelection */); } @Override public void setQualifier(ResourceQualifier qualifier) { NetworkCodeQualifier q = (NetworkCodeQualifier)qualifier; mText.setText(Integer.toString(q.getCode())); } } /** * Edit widget for {@link LanguageQualifier}. */ private class LanguageEdit extends QualifierEditBase { private Combo mLanguage; public LanguageEdit(Composite parent) { super(parent, LanguageQualifier.NAME); mLanguage = new Combo(this, SWT.DROP_DOWN); mLanguage.setLayoutData(new GridData(GridData.FILL_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("(2 letter code)"); } private void onLanguageChange() { // update the current config String value = mLanguage.getText(); if (value.length() == 0) { // empty string, means no qualifier. // Since the qualifier classes are immutable, and we don't want to // remove the qualifier from the configuration, we create a new default one. mSelectedConfiguration.setLanguageQualifier(new LanguageQualifier()); } else { LanguageQualifier qualifier = null; String segment = LanguageQualifier.getFolderSegment(value); if (segment != null) { qualifier = LanguageQualifier.getQualifier(segment); } if (qualifier != null) { mSelectedConfiguration.setLanguageQualifier(qualifier); } else { // Failure! Looks like the value is wrong (for instance a one letter string). mSelectedConfiguration.setLanguageQualifier(new LanguageQualifier()); } } // notify of change onChange(true /* keepSelection */); } @Override public void setQualifier(ResourceQualifier qualifier) { LanguageQualifier q = (LanguageQualifier)qualifier; String value = q.getValue(); if (value != null) { mLanguage.setText(value); } } } /** * Edit widget for {@link RegionQualifier}. */ private class RegionEdit extends QualifierEditBase { private Combo mRegion; public RegionEdit(Composite parent) { super(parent, RegionQualifier.NAME); mRegion = new Combo(this, SWT.DROP_DOWN); mRegion.setLayoutData(new GridData(GridData.FILL_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("(2 letter code)"); } private void onRegionChange() { // update the current config String value = mRegion.getText(); if (value.length() == 0) { // empty string, means no qualifier. // Since the qualifier classes are immutable, and we don't want to // remove the qualifier from the configuration, we create a new default one. mSelectedConfiguration.setRegionQualifier(new RegionQualifier()); } else { RegionQualifier qualifier = null; String segment = RegionQualifier.getFolderSegment(value); if (segment != null) { qualifier = RegionQualifier.getQualifier(segment); } if (qualifier != null) { mSelectedConfiguration.setRegionQualifier(qualifier); } else { // Failure! Looks like the value is wrong (for instance a one letter string). mSelectedConfiguration.setRegionQualifier(new RegionQualifier()); } } // notify of change onChange(true /* keepSelection */); } @Override public void setQualifier(ResourceQualifier qualifier) { RegionQualifier q = (RegionQualifier)qualifier; String value = q.getValue(); if (value != null) { mRegion.setText(q.getValue()); } } } /** * Edit widget for {@link ScreenOrientationQualifier}. */ private class OrientationEdit extends QualifierEditBase { private Combo mOrientation; public OrientationEdit(Composite parent) { super(parent, ScreenOrientationQualifier.NAME); mOrientation = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); ScreenOrientation[] soValues = ScreenOrientation.values(); for (ScreenOrientation value : soValues) { mOrientation.add(value.getDisplayValue()); } mOrientation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mOrientation.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { onOrientationChange(); } public void widgetSelected(SelectionEvent e) { onOrientationChange(); } }); } protected void onOrientationChange() { // update the current config int index = mOrientation.getSelectionIndex(); if (index != -1) { mSelectedConfiguration.setScreenOrientationQualifier(new ScreenOrientationQualifier( ScreenOrientation.getByIndex(index))); } else { // empty selection, means no qualifier. // Since the qualifier classes are immutable, and we don't want to // remove the qualifier from the configuration, we create a new default one. mSelectedConfiguration.setScreenOrientationQualifier( new ScreenOrientationQualifier()); } // notify of change onChange(true /* keepSelection */); } @Override public void setQualifier(ResourceQualifier qualifier) { ScreenOrientationQualifier q = (ScreenOrientationQualifier)qualifier; ScreenOrientation value = q.getValue(); if (value == null) { mOrientation.clearSelection(); } else { mOrientation.select(ScreenOrientation.getIndex(value)); } } } /** * Edit widget for {@link PixelDensityQualifier}. */ private class PixelDensityEdit extends QualifierEditBase { private Text mText; public PixelDensityEdit(Composite parent) { super(parent, PixelDensityQualifier.NAME); mText = new Text(this, SWT.BORDER); mText.addVerifyListener(new DensityVerifier()); mText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { onTextChange(); } }); mText.addFocusListener(new FocusAdapter() { @Override public void focusLost(FocusEvent e) { onTextChange(); } }); } private void onTextChange() { String value = mText.getText(); if (value.length() == 0) { // empty string, means a qualifier with no value. // Since the qualifier classes are immutable, and we don't want to // remove the qualifier from the configuration, we create a new default one. mSelectedConfiguration.setPixelDensityQualifier(new PixelDensityQualifier()); } else { try { PixelDensityQualifier qualifier = PixelDensityQualifier.getQualifier( PixelDensityQualifier.getFolderSegment(Integer.parseInt(value))); if (qualifier != null) { mSelectedConfiguration.setPixelDensityQualifier(qualifier); } else { // Failure! Looks like the value is wrong // (for instance a one letter string). // We do nothing in this case. return; } } catch (NumberFormatException nfe) { // Looks like the code is not a number. This should not happen since the text // field has a VerifyListener that prevents it. // We do nothing in this case. return; } } // notify of change onChange(true /* keepSelection */); } @Override public void setQualifier(ResourceQualifier qualifier) { PixelDensityQualifier q = (PixelDensityQualifier)qualifier; mText.setText(Integer.toString(q.getValue())); } } /** * Edit widget for {@link TouchScreenQualifier}. */ private class TouchEdit extends QualifierEditBase { private Combo mTouchScreen; public TouchEdit(Composite parent) { super(parent, TouchScreenQualifier.NAME); mTouchScreen = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); TouchScreenType[] tstValues = TouchScreenType.values(); for (TouchScreenType value : tstValues) { mTouchScreen.add(value.getDisplayValue()); } mTouchScreen.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mTouchScreen.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { onTouchChange(); } public void widgetSelected(SelectionEvent e) { onTouchChange(); } }); } protected void onTouchChange() { // update the current config int index = mTouchScreen.getSelectionIndex(); if (index != -1) { mSelectedConfiguration.setTouchTypeQualifier(new TouchScreenQualifier( TouchScreenType.getByIndex(index))); } else { // empty selection, means no qualifier. // Since the qualifier classes are immutable, and we don't want to // remove the qualifier from the configuration, we create a new default one. mSelectedConfiguration.setTouchTypeQualifier(new TouchScreenQualifier()); } // notify of change onChange(true /* keepSelection */); } @Override public void setQualifier(ResourceQualifier qualifier) { TouchScreenQualifier q = (TouchScreenQualifier)qualifier; TouchScreenType value = q.getValue(); if (value == null) { mTouchScreen.clearSelection(); } else { mTouchScreen.select(TouchScreenType.getIndex(value)); } } } /** * Edit widget for {@link KeyboardStateQualifier}. */ private class KeyboardEdit extends QualifierEditBase { private Combo mKeyboard; public KeyboardEdit(Composite parent) { super(parent, KeyboardStateQualifier.NAME); mKeyboard = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); KeyboardState[] ksValues = KeyboardState.values(); for (KeyboardState value : ksValues) { mKeyboard.add(value.getDisplayValue()); } mKeyboard.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mKeyboard.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { onKeyboardChange(); } public void widgetSelected(SelectionEvent e) { onKeyboardChange(); } }); } protected void onKeyboardChange() { // update the current config int index = mKeyboard.getSelectionIndex(); if (index != -1) { mSelectedConfiguration.setKeyboardStateQualifier(new KeyboardStateQualifier( KeyboardState.getByIndex(index))); } else { // empty selection, means no qualifier. // Since the qualifier classes are immutable, and we don't want to // remove the qualifier from the configuration, we create a new default one. mSelectedConfiguration.setKeyboardStateQualifier( new KeyboardStateQualifier()); } // notify of change onChange(true /* keepSelection */); } @Override public void setQualifier(ResourceQualifier qualifier) { KeyboardStateQualifier q = (KeyboardStateQualifier)qualifier; KeyboardState value = q.getValue(); if (value == null) { mKeyboard.clearSelection(); } else { mKeyboard.select(KeyboardState.getIndex(value)); } } } /** * Edit widget for {@link TextInputMethodQualifier}. */ private class TextInputEdit extends QualifierEditBase { private Combo mTextInput; public TextInputEdit(Composite parent) { super(parent, TextInputMethodQualifier.NAME); mTextInput = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); TextInputMethod[] timValues = TextInputMethod.values(); for (TextInputMethod value : timValues) { mTextInput.add(value.getDisplayValue()); } mTextInput.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mTextInput.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { onTextInputChange(); } public void widgetSelected(SelectionEvent e) { onTextInputChange(); } }); } protected void onTextInputChange() { // update the current config int index = mTextInput.getSelectionIndex(); if (index != -1) { mSelectedConfiguration.setTextInputMethodQualifier(new TextInputMethodQualifier( TextInputMethod.getByIndex(index))); } else { // empty selection, means no qualifier. // Since the qualifier classes are immutable, and we don't want to // remove the qualifier from the configuration, we create a new default one. mSelectedConfiguration.setTextInputMethodQualifier( new TextInputMethodQualifier()); } // notify of change onChange(true /* keepSelection */); } @Override public void setQualifier(ResourceQualifier qualifier) { TextInputMethodQualifier q = (TextInputMethodQualifier)qualifier; TextInputMethod value = q.getValue(); if (value == null) { mTextInput.clearSelection(); } else { mTextInput.select(TextInputMethod.getIndex(value)); } } } /** * Edit widget for {@link NavigationMethodQualifier}. */ private class NavigationEdit extends QualifierEditBase { private Combo mNavigation; public NavigationEdit(Composite parent) { super(parent, NavigationMethodQualifier.NAME); mNavigation = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY); NavigationMethod[] nmValues = NavigationMethod.values(); for (NavigationMethod value : nmValues) { mNavigation.add(value.getDisplayValue()); } mNavigation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mNavigation.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { onNavigationChange(); } public void widgetSelected(SelectionEvent e) { onNavigationChange(); } }); } protected void onNavigationChange() { // update the current config int index = mNavigation.getSelectionIndex(); if (index != -1) { mSelectedConfiguration.setNavigationMethodQualifier(new NavigationMethodQualifier( NavigationMethod.getByIndex(index))); } else { // empty selection, means no qualifier. // Since the qualifier classes are immutable, and we don't want to // remove the qualifier from the configuration, we create a new default one. mSelectedConfiguration.setNavigationMethodQualifier( new NavigationMethodQualifier()); } // notify of change onChange(true /* keepSelection */); } @Override public void setQualifier(ResourceQualifier qualifier) { NavigationMethodQualifier q = (NavigationMethodQualifier)qualifier; NavigationMethod value = q.getValue(); if (value == null) { mNavigation.clearSelection(); } else { mNavigation.select(NavigationMethod.getIndex(value)); } } } /** * Edit widget for {@link ScreenDimensionQualifier}. */ private class ScreenDimensionEdit extends QualifierEditBase { private Text mSize1; private Text mSize2; public ScreenDimensionEdit(Composite parent) { super(parent, ScreenDimensionQualifier.NAME); ModifyListener modifyListener = new ModifyListener() { public void modifyText(ModifyEvent e) { onSizeChange(); } }; FocusAdapter focusListener = new FocusAdapter() { @Override public void focusLost(FocusEvent e) { onSizeChange(); } }; mSize1 = new Text(this, SWT.BORDER); mSize1.addVerifyListener(new DimensionVerifier()); mSize1.addModifyListener(modifyListener); mSize1.addFocusListener(focusListener); mSize2 = new Text(this, SWT.BORDER); mSize2.addVerifyListener(new DimensionVerifier()); mSize2.addModifyListener(modifyListener); mSize2.addFocusListener(focusListener); } private void onSizeChange() { // update the current config String size1 = mSize1.getText(); String size2 = mSize2.getText(); if (size1.length() == 0 || size2.length() == 0) { // if one of the strings is empty, reset to no qualifier. // Since the qualifier classes are immutable, and we don't want to // remove the qualifier from the configuration, we create a new default one. mSelectedConfiguration.setScreenDimensionQualifier(new ScreenDimensionQualifier()); } else { ScreenDimensionQualifier qualifier = ScreenDimensionQualifier.getQualifier(size1, size2); if (qualifier != null) { mSelectedConfiguration.setScreenDimensionQualifier(qualifier); } else { // Failure! Looks like the value is wrong, reset the qualifier // Since the qualifier classes are immutable, and we don't want to // remove the qualifier from the configuration, we create a new default one. mSelectedConfiguration.setScreenDimensionQualifier( new ScreenDimensionQualifier()); } } // notify of change onChange(true /* keepSelection */); } @Override public void setQualifier(ResourceQualifier qualifier) { ScreenDimensionQualifier q = (ScreenDimensionQualifier)qualifier; mSize1.setText(Integer.toString(q.getValue1())); mSize2.setText(Integer.toString(q.getValue2())); } } }