Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.ide.eclipse.adt.internal.ui;
     18 
     19 import com.android.AndroidConstants;
     20 import com.android.ide.common.resources.configuration.CountryCodeQualifier;
     21 import com.android.ide.common.resources.configuration.DensityQualifier;
     22 import com.android.ide.common.resources.configuration.FolderConfiguration;
     23 import com.android.ide.common.resources.configuration.KeyboardStateQualifier;
     24 import com.android.ide.common.resources.configuration.LanguageQualifier;
     25 import com.android.ide.common.resources.configuration.NavigationMethodQualifier;
     26 import com.android.ide.common.resources.configuration.NavigationStateQualifier;
     27 import com.android.ide.common.resources.configuration.NetworkCodeQualifier;
     28 import com.android.ide.common.resources.configuration.NightModeQualifier;
     29 import com.android.ide.common.resources.configuration.RegionQualifier;
     30 import com.android.ide.common.resources.configuration.ResourceQualifier;
     31 import com.android.ide.common.resources.configuration.ScreenDimensionQualifier;
     32 import com.android.ide.common.resources.configuration.ScreenHeightQualifier;
     33 import com.android.ide.common.resources.configuration.ScreenOrientationQualifier;
     34 import com.android.ide.common.resources.configuration.ScreenRatioQualifier;
     35 import com.android.ide.common.resources.configuration.ScreenSizeQualifier;
     36 import com.android.ide.common.resources.configuration.ScreenWidthQualifier;
     37 import com.android.ide.common.resources.configuration.SmallestScreenWidthQualifier;
     38 import com.android.ide.common.resources.configuration.TextInputMethodQualifier;
     39 import com.android.ide.common.resources.configuration.TouchScreenQualifier;
     40 import com.android.ide.common.resources.configuration.UiModeQualifier;
     41 import com.android.ide.common.resources.configuration.VersionQualifier;
     42 import com.android.ide.eclipse.adt.internal.resources.ResourceHelper;
     43 import com.android.resources.Density;
     44 import com.android.resources.Keyboard;
     45 import com.android.resources.KeyboardState;
     46 import com.android.resources.Navigation;
     47 import com.android.resources.NavigationState;
     48 import com.android.resources.NightMode;
     49 import com.android.resources.ResourceEnum;
     50 import com.android.resources.ScreenOrientation;
     51 import com.android.resources.ScreenRatio;
     52 import com.android.resources.ScreenSize;
     53 import com.android.resources.TouchScreen;
     54 import com.android.resources.UiMode;
     55 
     56 import org.eclipse.jface.viewers.ILabelProviderListener;
     57 import org.eclipse.jface.viewers.ISelection;
     58 import org.eclipse.jface.viewers.ISelectionChangedListener;
     59 import org.eclipse.jface.viewers.IStructuredContentProvider;
     60 import org.eclipse.jface.viewers.IStructuredSelection;
     61 import org.eclipse.jface.viewers.ITableLabelProvider;
     62 import org.eclipse.jface.viewers.SelectionChangedEvent;
     63 import org.eclipse.jface.viewers.StructuredSelection;
     64 import org.eclipse.jface.viewers.TableViewer;
     65 import org.eclipse.jface.viewers.Viewer;
     66 import org.eclipse.swt.SWT;
     67 import org.eclipse.swt.custom.StackLayout;
     68 import org.eclipse.swt.events.ControlAdapter;
     69 import org.eclipse.swt.events.ControlEvent;
     70 import org.eclipse.swt.events.FocusAdapter;
     71 import org.eclipse.swt.events.FocusEvent;
     72 import org.eclipse.swt.events.ModifyEvent;
     73 import org.eclipse.swt.events.ModifyListener;
     74 import org.eclipse.swt.events.SelectionAdapter;
     75 import org.eclipse.swt.events.SelectionEvent;
     76 import org.eclipse.swt.events.SelectionListener;
     77 import org.eclipse.swt.events.VerifyEvent;
     78 import org.eclipse.swt.events.VerifyListener;
     79 import org.eclipse.swt.graphics.Image;
     80 import org.eclipse.swt.graphics.Rectangle;
     81 import org.eclipse.swt.layout.GridData;
     82 import org.eclipse.swt.layout.GridLayout;
     83 import org.eclipse.swt.widgets.Button;
     84 import org.eclipse.swt.widgets.Combo;
     85 import org.eclipse.swt.widgets.Composite;
     86 import org.eclipse.swt.widgets.Label;
     87 import org.eclipse.swt.widgets.Table;
     88 import org.eclipse.swt.widgets.TableColumn;
     89 import org.eclipse.swt.widgets.Text;
     90 
     91 import java.util.ArrayList;
     92 import java.util.HashMap;
     93 
     94 /**
     95  * Custom UI widget to let user build a Folder configuration.
     96  * <p/>
     97  * To use this, instantiate somewhere in the UI and then:
     98  * <ul>
     99  * <li>Use {@link #setConfiguration(String)} or {@link #setConfiguration(FolderConfiguration)}.
    100  * <li>Retrieve the configuration using {@link #getConfiguration(FolderConfiguration)}.
    101  * </ul>
    102  */
    103 public class ConfigurationSelector extends Composite {
    104 
    105     public static final int WIDTH_HINT = 600;
    106     public static final int HEIGHT_HINT = 250;
    107 
    108     private Runnable mOnChangeListener;
    109 
    110     private TableViewer mFullTableViewer;
    111     private TableViewer mSelectionTableViewer;
    112     private Button mAddButton;
    113     private Button mRemoveButton;
    114     private StackLayout mStackLayout;
    115 
    116     private boolean mOnRefresh = false;
    117 
    118     private final FolderConfiguration mBaseConfiguration = new FolderConfiguration();
    119     private final FolderConfiguration mSelectedConfiguration = new FolderConfiguration();
    120 
    121     private final HashMap<Class<? extends ResourceQualifier>, QualifierEditBase> mUiMap =
    122         new HashMap<Class<? extends ResourceQualifier>, QualifierEditBase>();
    123     private final SelectorMode mMode;
    124     private Composite mQualifierEditParent;
    125     private IQualifierFilter mQualifierFilter;
    126 
    127     /**
    128      * Basic of {@link VerifyListener} to only accept digits.
    129      */
    130     private static class DigitVerifier implements VerifyListener {
    131         @Override
    132         public void verifyText(VerifyEvent e) {
    133             // check for digit only.
    134             for (int i = 0 ; i < e.text.length(); i++) {
    135                 char letter = e.text.charAt(i);
    136                 if (letter < '0' || letter > '9') {
    137                     e.doit = false;
    138                     return;
    139                 }
    140             }
    141         }
    142     }
    143 
    144     /**
    145      * Implementation of {@link VerifyListener} for Country Code qualifiers.
    146      */
    147     public static class MobileCodeVerifier extends DigitVerifier {
    148         @Override
    149         public void verifyText(VerifyEvent e) {
    150             super.verifyText(e);
    151 
    152             // basic tests passed?
    153             if (e.doit) {
    154                 // check the max 3 digits.
    155                 if (e.text.length() - e.end + e.start +
    156                         ((Text)e.getSource()).getText().length() > 3) {
    157                     e.doit = false;
    158                 }
    159             }
    160         }
    161     }
    162 
    163     /**
    164      * Implementation of {@link VerifyListener} for the Language and Region qualifiers.
    165      */
    166     public static class LanguageRegionVerifier implements VerifyListener {
    167         @Override
    168         public void verifyText(VerifyEvent e) {
    169             // check for length
    170             if (e.text.length() - e.end + e.start + ((Combo)e.getSource()).getText().length() > 2) {
    171                 e.doit = false;
    172                 return;
    173             }
    174 
    175             // check for lower case only.
    176             for (int i = 0 ; i < e.text.length(); i++) {
    177                 char letter = e.text.charAt(i);
    178                 if ((letter < 'a' || letter > 'z') && (letter < 'A' || letter > 'Z')) {
    179                     e.doit = false;
    180                     return;
    181                 }
    182             }
    183         }
    184     }
    185 
    186     /**
    187      * Implementation of {@link VerifyListener} for the Density qualifier.
    188      */
    189     public static class DensityVerifier extends DigitVerifier { }
    190 
    191     /**
    192      * Implementation of {@link VerifyListener} for the Screen Dimension qualifier.
    193      */
    194     public static class DimensionVerifier extends DigitVerifier { }
    195 
    196     /**
    197      * Enum for the state of the configuration being created.
    198      */
    199     public enum ConfigurationState {
    200         OK, INVALID_CONFIG, REGION_WITHOUT_LANGUAGE;
    201     }
    202 
    203     /**
    204      * Behavior mode for the Selector.
    205      *
    206      * @see #DEFAULT
    207      * @see #DEVICE_ONLY
    208      * @see #CONFIG_ONLY
    209      */
    210     public enum SelectorMode {
    211         /** the default mode */
    212         DEFAULT,
    213         /** mode forcing the qualifier values to be valid on a device.
    214          * For instance {@link Density#NODPI} is a valid qualifier for a resource configuration but
    215          * this is not valid on a device */
    216         DEVICE_ONLY,
    217         /** mode where only the specific config can be edited. The user can only select
    218          * which non-empty qualifier to select. */
    219         CONFIG_ONLY;
    220     }
    221 
    222     /**
    223      * A filter for {@link ResourceQualifier}.
    224      * @see ConfigurationSelector#setQualifierFilter(IQualifierFilter)
    225      */
    226     public interface IQualifierFilter {
    227         /**
    228          * Returns true of the qualifier is accepted.
    229          */
    230         boolean accept(ResourceQualifier qualifier);
    231     }
    232 
    233     /**
    234      * Creates the selector.
    235      * <p/>
    236      * The {@link SelectorMode} changes the behavior of the selector depending on what is being
    237      * edited (a device config, a resource config, a given configuration).
    238      *
    239      * @param parent the composite parent.
    240      * @param mode the mode for the selector.
    241      */
    242     public ConfigurationSelector(Composite parent, SelectorMode mode) {
    243         super(parent, SWT.NONE);
    244 
    245         mMode  = mode;
    246         mBaseConfiguration.createDefault();
    247 
    248         GridLayout gl = new GridLayout(4, false);
    249         gl.marginWidth = gl.marginHeight = 0;
    250         setLayout(gl);
    251 
    252         // first column is the first table
    253         final Table fullTable = new Table(this, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER);
    254         fullTable.setLayoutData(new GridData(GridData.FILL_BOTH));
    255         fullTable.setHeaderVisible(true);
    256         fullTable.setLinesVisible(true);
    257 
    258         // create the column
    259         final TableColumn fullTableColumn = new TableColumn(fullTable, SWT.LEFT);
    260         // set the header
    261         fullTableColumn.setText("Available Qualifiers");
    262 
    263         fullTable.addControlListener(new ControlAdapter() {
    264             @Override
    265             public void controlResized(ControlEvent e) {
    266                 Rectangle r = fullTable.getClientArea();
    267                 fullTableColumn.setWidth(r.width);
    268             }
    269         });
    270 
    271         mFullTableViewer = new TableViewer(fullTable);
    272         mFullTableViewer.setContentProvider(new QualifierContentProvider());
    273         // the label provider must return the value of the label only if the mode is
    274         // CONFIG_ONLY
    275         mFullTableViewer.setLabelProvider(new QualifierLabelProvider(
    276                 mMode == SelectorMode.CONFIG_ONLY));
    277         mFullTableViewer.setInput(mBaseConfiguration);
    278         mFullTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
    279             @Override
    280             public void selectionChanged(SelectionChangedEvent event) {
    281                 ISelection selection = event.getSelection();
    282                 if (selection instanceof IStructuredSelection) {
    283                     IStructuredSelection structSelection = (IStructuredSelection)selection;
    284                     Object first = structSelection.getFirstElement();
    285 
    286                     if (first instanceof ResourceQualifier) {
    287                         mAddButton.setEnabled(true);
    288                         return;
    289                     }
    290                 }
    291 
    292                 mAddButton.setEnabled(false);
    293             }
    294         });
    295 
    296         // 2nd column is the left/right arrow button
    297         Composite buttonComposite = new Composite(this, SWT.NONE);
    298         gl = new GridLayout(1, false);
    299         gl.marginWidth = gl.marginHeight = 0;
    300         buttonComposite.setLayout(gl);
    301         buttonComposite.setLayoutData(new GridData(GridData.FILL_VERTICAL));
    302 
    303         new Composite(buttonComposite, SWT.NONE);
    304         mAddButton = new Button(buttonComposite, SWT.BORDER | SWT.PUSH);
    305         mAddButton.setText("->");
    306         mAddButton.setEnabled(false);
    307         mAddButton.addSelectionListener(new SelectionAdapter() {
    308             @Override
    309             public void widgetSelected(SelectionEvent e) {
    310                 IStructuredSelection selection =
    311                     (IStructuredSelection)mFullTableViewer.getSelection();
    312 
    313                 Object first = selection.getFirstElement();
    314                 if (first instanceof ResourceQualifier) {
    315                     ResourceQualifier qualifier = (ResourceQualifier)first;
    316 
    317                     mBaseConfiguration.removeQualifier(qualifier);
    318                     mSelectedConfiguration.addQualifier(qualifier);
    319 
    320                     mFullTableViewer.refresh();
    321                     mSelectionTableViewer.refresh();
    322                     mSelectionTableViewer.setSelection(new StructuredSelection(qualifier), true);
    323 
    324                     onChange(false /* keepSelection */);
    325                 }
    326             }
    327         });
    328 
    329         mRemoveButton = new Button(buttonComposite, SWT.BORDER | SWT.PUSH);
    330         mRemoveButton.setText("<-");
    331         mRemoveButton.setEnabled(false);
    332         mRemoveButton.addSelectionListener(new SelectionAdapter() {
    333             @Override
    334             public void widgetSelected(SelectionEvent e) {
    335                 IStructuredSelection selection =
    336                     (IStructuredSelection)mSelectionTableViewer.getSelection();
    337 
    338                 Object first = selection.getFirstElement();
    339                 if (first instanceof ResourceQualifier) {
    340                     ResourceQualifier qualifier = (ResourceQualifier)first;
    341 
    342                     mSelectedConfiguration.removeQualifier(qualifier);
    343                     mBaseConfiguration.addQualifier(qualifier);
    344 
    345                     mFullTableViewer.refresh();
    346                     mSelectionTableViewer.refresh();
    347 
    348                     onChange(false /* keepSelection */);
    349                 }
    350             }
    351         });
    352 
    353         // 3rd column is the selected config table
    354         final Table selectionTable = new Table(this, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER);
    355         selectionTable.setLayoutData(new GridData(GridData.FILL_BOTH));
    356         selectionTable.setHeaderVisible(true);
    357         selectionTable.setLinesVisible(true);
    358 
    359         // create the column
    360         final TableColumn selectionTableColumn = new TableColumn(selectionTable, SWT.LEFT);
    361         // set the header
    362         selectionTableColumn.setText("Chosen Qualifiers");
    363 
    364         selectionTable.addControlListener(new ControlAdapter() {
    365             @Override
    366             public void controlResized(ControlEvent e) {
    367                 Rectangle r = selectionTable.getClientArea();
    368                 selectionTableColumn.setWidth(r.width);
    369             }
    370         });
    371         mSelectionTableViewer = new TableViewer(selectionTable);
    372         mSelectionTableViewer.setContentProvider(new QualifierContentProvider());
    373         // always show the qualifier value in this case.
    374         mSelectionTableViewer.setLabelProvider(new QualifierLabelProvider(
    375                 true /* showQualifierValue */));
    376         mSelectionTableViewer.setInput(mSelectedConfiguration);
    377         mSelectionTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
    378             @Override
    379             public void selectionChanged(SelectionChangedEvent event) {
    380                 // ignore selection changes during resfreshes in some cases.
    381                 if (mOnRefresh) {
    382                     return;
    383                 }
    384 
    385                 ISelection selection = event.getSelection();
    386                 if (selection instanceof IStructuredSelection) {
    387                     IStructuredSelection structSelection = (IStructuredSelection)selection;
    388 
    389                     if (structSelection.isEmpty() == false) {
    390                         Object first = structSelection.getFirstElement();
    391 
    392                         if (first instanceof ResourceQualifier) {
    393                             mRemoveButton.setEnabled(true);
    394 
    395                             if (mMode != SelectorMode.CONFIG_ONLY) {
    396                                 QualifierEditBase composite = mUiMap.get(first.getClass());
    397 
    398                                 if (composite != null) {
    399                                     composite.setQualifier((ResourceQualifier)first);
    400                                 }
    401 
    402                                 mStackLayout.topControl = composite;
    403                                 mQualifierEditParent.layout();
    404                             }
    405 
    406                             return;
    407                         }
    408                     } else {
    409                         if (mMode != SelectorMode.CONFIG_ONLY) {
    410                             mStackLayout.topControl = null;
    411                             mQualifierEditParent.layout();
    412                         }
    413                     }
    414                 }
    415 
    416                 mRemoveButton.setEnabled(false);
    417             }
    418         });
    419 
    420         if (mMode != SelectorMode.CONFIG_ONLY) {
    421             // 4th column is the detail of the selected qualifier
    422             mQualifierEditParent = new Composite(this, SWT.NONE);
    423             mQualifierEditParent.setLayout(mStackLayout = new StackLayout());
    424             mQualifierEditParent.setLayoutData(new GridData(GridData.FILL_VERTICAL));
    425 
    426             // create the UI for all the qualifiers, and associate them to the
    427             // ResourceQualifer class.
    428             mUiMap.put(CountryCodeQualifier.class, new MCCEdit(mQualifierEditParent));
    429             mUiMap.put(NetworkCodeQualifier.class, new MNCEdit(mQualifierEditParent));
    430             mUiMap.put(LanguageQualifier.class, new LanguageEdit(mQualifierEditParent));
    431             mUiMap.put(RegionQualifier.class, new RegionEdit(mQualifierEditParent));
    432             mUiMap.put(SmallestScreenWidthQualifier.class,
    433                     new SmallestScreenWidthEdit(mQualifierEditParent));
    434             mUiMap.put(ScreenWidthQualifier.class, new ScreenWidthEdit(mQualifierEditParent));
    435             mUiMap.put(ScreenHeightQualifier.class, new ScreenHeightEdit(mQualifierEditParent));
    436             mUiMap.put(ScreenSizeQualifier.class, new ScreenSizeEdit(mQualifierEditParent));
    437             mUiMap.put(ScreenRatioQualifier.class, new ScreenRatioEdit(mQualifierEditParent));
    438             mUiMap.put(ScreenOrientationQualifier.class, new OrientationEdit(mQualifierEditParent));
    439             mUiMap.put(UiModeQualifier.class, new UiModeEdit(mQualifierEditParent));
    440             mUiMap.put(NightModeQualifier.class, new NightModeEdit(mQualifierEditParent));
    441             mUiMap.put(DensityQualifier.class, new DensityEdit(mQualifierEditParent));
    442             mUiMap.put(TouchScreenQualifier.class, new TouchEdit(mQualifierEditParent));
    443             mUiMap.put(KeyboardStateQualifier.class, new KeyboardEdit(mQualifierEditParent));
    444             mUiMap.put(TextInputMethodQualifier.class, new TextInputEdit(mQualifierEditParent));
    445             mUiMap.put(NavigationStateQualifier.class,
    446                     new NavigationStateEdit(mQualifierEditParent));
    447             mUiMap.put(NavigationMethodQualifier.class, new NavigationEdit(mQualifierEditParent));
    448             mUiMap.put(ScreenDimensionQualifier.class,
    449                     new ScreenDimensionEdit(mQualifierEditParent));
    450             mUiMap.put(VersionQualifier.class, new VersionEdit(mQualifierEditParent));
    451         }
    452     }
    453 
    454     /**
    455      * Sets a {@link IQualifierFilter}. If non null, this will restrict the qualifiers that
    456      * can be chosen.
    457      * @param filter the filter to set.
    458      */
    459     public void setQualifierFilter(IQualifierFilter filter) {
    460         mQualifierFilter = filter;
    461     }
    462 
    463     /**
    464      * Sets a listener to be notified when the configuration changes.
    465      * @param listener A {@link Runnable} whose <code>run()</code> method is called when the
    466      * configuration is changed. The method is called from the UI thread.
    467      */
    468     public void setOnChangeListener(Runnable listener) {
    469         mOnChangeListener = listener;
    470     }
    471 
    472     /**
    473      * Initialize the UI with a given {@link FolderConfiguration}. This must
    474      * be called from the UI thread.
    475      * @param config The configuration.
    476      */
    477     public void setConfiguration(FolderConfiguration config) {
    478 
    479         if (mMode != SelectorMode.CONFIG_ONLY) {
    480             mSelectedConfiguration.set(config, true /*nonFakeValuesOnly*/);
    481 
    482             // create the base config, which is the default config minus the qualifiers
    483             // in SelectedConfiguration
    484             mBaseConfiguration.substract(mSelectedConfiguration);
    485         } else {
    486             // set the base config to the edited config.
    487             // reset the config to be empty
    488             mBaseConfiguration.reset();
    489             mBaseConfiguration.set(config, true /*nonFakeValuesOnly*/);
    490         }
    491 
    492         mSelectionTableViewer.refresh();
    493         mFullTableViewer.refresh();
    494     }
    495 
    496     /**
    497      * Initialize the UI with the configuration represented by a resource folder name.
    498      * This must be called from the UI thread.
    499      *
    500      * @param folderSegments the segments of the folder name,
    501      *                       split using {@link FolderConfiguration#QUALIFIER_SEP}.
    502      * @return true if success, or false if the folder name is not a valid name.
    503      */
    504     public boolean setConfiguration(String[] folderSegments) {
    505         FolderConfiguration config = FolderConfiguration.getConfig(folderSegments);
    506 
    507         if (config == null) {
    508             return false;
    509         }
    510 
    511         setConfiguration(config);
    512 
    513         return true;
    514     }
    515 
    516     /**
    517      * Initialize the UI with the configuration represented by a resource folder name.
    518      * This must be called from the UI thread.
    519      * @param folderName the name of the folder.
    520      * @return true if success, or false if the folder name is not a valid name.
    521      */
    522     public boolean setConfiguration(String folderName) {
    523         // split the name of the folder in segments.
    524         String[] folderSegments = folderName.split(AndroidConstants.RES_QUALIFIER_SEP);
    525 
    526         return setConfiguration(folderSegments);
    527     }
    528 
    529     /**
    530      * Gets the configuration as setup by the widget.
    531      * @param config the {@link FolderConfiguration} object to be filled with the information
    532      * from the UI.
    533      */
    534     public void getConfiguration(FolderConfiguration config) {
    535         config.set(mSelectedConfiguration);
    536     }
    537 
    538     /**
    539      * Returns the state of the configuration being edited/created.
    540      */
    541     public ConfigurationState getState() {
    542         if (mSelectedConfiguration.getInvalidQualifier() != null) {
    543             return ConfigurationState.INVALID_CONFIG;
    544         }
    545 
    546         if (mSelectedConfiguration.checkRegion() == false) {
    547             return ConfigurationState.REGION_WITHOUT_LANGUAGE;
    548         }
    549 
    550         return ConfigurationState.OK;
    551     }
    552 
    553     /**
    554      * Returns the first invalid qualifier of the configuration being edited/created,
    555      * or <code>null<code> if they are all valid (or if none exists).
    556      * <p/>If {@link #getState()} return {@link ConfigurationState#INVALID_CONFIG} then this will
    557      * not return <code>null</code>.
    558      */
    559     public ResourceQualifier getInvalidQualifier() {
    560         return mSelectedConfiguration.getInvalidQualifier();
    561     }
    562 
    563     /**
    564      * Handle changes in the configuration.
    565      * @param keepSelection if <code>true</code> attemps to avoid triggering selection change in
    566      * {@link #mSelectedConfiguration}.
    567      */
    568     private void onChange(boolean keepSelection) {
    569         ISelection selection = null;
    570         if (keepSelection) {
    571             mOnRefresh = true;
    572             selection = mSelectionTableViewer.getSelection();
    573         }
    574 
    575         mSelectionTableViewer.refresh(true);
    576 
    577         if (keepSelection) {
    578             mSelectionTableViewer.setSelection(selection);
    579             mOnRefresh = false;
    580         }
    581 
    582         if (mOnChangeListener != null) {
    583             mOnChangeListener.run();
    584         }
    585     }
    586 
    587     private void fillCombo(Combo combo, ResourceEnum[] resEnums) {
    588         for (ResourceEnum resEnum : resEnums) {
    589             // only add the enum if:
    590             // not in device mode OR (device mode is true and) it's a valid device value.
    591             // Also, always ignore fake values.
    592             if ((mMode == SelectorMode.DEFAULT || resEnum.isValidValueForDevice()) &&
    593                     resEnum.isFakeValue() == false) {
    594                 combo.add(resEnum.getShortDisplayValue());
    595             }
    596         }
    597     }
    598 
    599     /**
    600      * Content provider around a {@link FolderConfiguration}.
    601      */
    602     private class QualifierContentProvider implements IStructuredContentProvider {
    603 
    604         private FolderConfiguration mInput;
    605 
    606         public QualifierContentProvider() {
    607         }
    608 
    609         @Override
    610         public void dispose() {
    611             // pass
    612         }
    613 
    614         @Override
    615         public Object[] getElements(Object inputElement) {
    616             // default easy case
    617             if (mQualifierFilter == null) {
    618                 return mInput.getQualifiers();
    619             }
    620 
    621             // in this case we have to compute the list
    622             ArrayList<ResourceQualifier> list = new ArrayList<ResourceQualifier>();
    623             for (ResourceQualifier qual : mInput.getQualifiers()) {
    624                 if (mQualifierFilter.accept(qual)) {
    625                     list.add(qual);
    626                 }
    627             }
    628 
    629             return list.toArray();
    630         }
    631 
    632         @Override
    633         public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
    634             mInput = null;
    635             if (newInput instanceof FolderConfiguration) {
    636                 mInput = (FolderConfiguration)newInput;
    637             }
    638         }
    639     }
    640 
    641     /**
    642      * Label provider for {@link ResourceQualifier} objects.
    643      */
    644     private static class QualifierLabelProvider implements ITableLabelProvider {
    645 
    646         private final boolean mShowQualifierValue;
    647 
    648         public QualifierLabelProvider(boolean showQualifierValue) {
    649             mShowQualifierValue = showQualifierValue;
    650         }
    651 
    652         @Override
    653         public String getColumnText(Object element, int columnIndex) {
    654             // only one column, so we can ignore columnIndex
    655             if (element instanceof ResourceQualifier) {
    656                 if (mShowQualifierValue) {
    657                     String value = ((ResourceQualifier)element).getShortDisplayValue();
    658                     if (value.length() == 0) {
    659                         return String.format("%1$s (?)",
    660                                 ((ResourceQualifier)element).getShortName());
    661                     } else {
    662                         return value;
    663                     }
    664 
    665                 } else {
    666                     return ((ResourceQualifier)element).getShortName();
    667                 }
    668             }
    669 
    670             return null;
    671         }
    672 
    673         @Override
    674         public Image getColumnImage(Object element, int columnIndex) {
    675             // only one column, so we can ignore columnIndex
    676             if (element instanceof ResourceQualifier) {
    677                 return ResourceHelper.getIcon(((ResourceQualifier)element).getClass());
    678             }
    679 
    680             return null;
    681         }
    682 
    683         @Override
    684         public void addListener(ILabelProviderListener listener) {
    685             // pass
    686         }
    687 
    688         @Override
    689         public void dispose() {
    690             // pass
    691         }
    692 
    693         @Override
    694         public boolean isLabelProperty(Object element, String property) {
    695             // pass
    696             return false;
    697         }
    698 
    699         @Override
    700         public void removeListener(ILabelProviderListener listener) {
    701             // pass
    702         }
    703     }
    704 
    705     /**
    706      * Base class for Edit widget for {@link ResourceQualifier}.
    707      */
    708     private abstract static class QualifierEditBase extends Composite {
    709 
    710         public QualifierEditBase(Composite parent, String title) {
    711             super(parent, SWT.NONE);
    712             setLayout(new GridLayout(1, false));
    713 
    714             new Label(this, SWT.NONE).setText(title);
    715         }
    716 
    717         public abstract void setQualifier(ResourceQualifier qualifier);
    718     }
    719 
    720     /**
    721      * Edit widget for {@link CountryCodeQualifier}.
    722      */
    723     private class MCCEdit extends QualifierEditBase {
    724 
    725         private Text mText;
    726 
    727         public MCCEdit(Composite parent) {
    728             super(parent, CountryCodeQualifier.NAME);
    729 
    730             mText = new Text(this, SWT.BORDER);
    731             mText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    732             mText.addVerifyListener(new MobileCodeVerifier());
    733             mText.addModifyListener(new ModifyListener() {
    734                 @Override
    735                 public void modifyText(ModifyEvent e) {
    736                     onTextChange();
    737                 }
    738             });
    739 
    740             mText.addFocusListener(new FocusAdapter() {
    741                 @Override
    742                 public void focusLost(FocusEvent e) {
    743                     onTextChange();
    744                 }
    745             });
    746 
    747             new Label(this, SWT.NONE).setText("(3 digit code)");
    748         }
    749 
    750         private void onTextChange() {
    751             String value = mText.getText();
    752 
    753             if (value.length() == 0) {
    754                 // empty string, means a qualifier with no value.
    755                 // Since the qualifier classes are immutable, and we don't want to
    756                 // remove the qualifier from the configuration, we create a new default one.
    757                 mSelectedConfiguration.setCountryCodeQualifier(new CountryCodeQualifier());
    758             } else {
    759                 try {
    760                     CountryCodeQualifier qualifier = CountryCodeQualifier.getQualifier(
    761                             CountryCodeQualifier.getFolderSegment(Integer.parseInt(value)));
    762                     if (qualifier != null) {
    763                         mSelectedConfiguration.setCountryCodeQualifier(qualifier);
    764                     } else {
    765                         // Failure! Looks like the value is wrong
    766                         // (for instance not exactly 3 digits).
    767                         mSelectedConfiguration.setCountryCodeQualifier(new CountryCodeQualifier());
    768                     }
    769                 } catch (NumberFormatException nfe) {
    770                     // Looks like the code is not a number. This should not happen since the text
    771                     // field has a VerifyListener that prevents it.
    772                     mSelectedConfiguration.setCountryCodeQualifier(new CountryCodeQualifier());
    773                 }
    774             }
    775 
    776             // notify of change
    777             onChange(true /* keepSelection */);
    778         }
    779 
    780         @Override
    781         public void setQualifier(ResourceQualifier qualifier) {
    782             CountryCodeQualifier q = (CountryCodeQualifier)qualifier;
    783 
    784             mText.setText(Integer.toString(q.getCode()));
    785         }
    786     }
    787 
    788     /**
    789      * Edit widget for {@link NetworkCodeQualifier}.
    790      */
    791     private class MNCEdit extends QualifierEditBase {
    792         private Text mText;
    793 
    794         public MNCEdit(Composite parent) {
    795             super(parent, NetworkCodeQualifier.NAME);
    796 
    797             mText = new Text(this, SWT.BORDER);
    798             mText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    799             mText.addVerifyListener(new MobileCodeVerifier());
    800             mText.addModifyListener(new ModifyListener() {
    801                 @Override
    802                 public void modifyText(ModifyEvent e) {
    803                     onTextChange();
    804                 }
    805             });
    806             mText.addFocusListener(new FocusAdapter() {
    807                 @Override
    808                 public void focusLost(FocusEvent e) {
    809                     onTextChange();
    810                 }
    811             });
    812 
    813             new Label(this, SWT.NONE).setText("(1-3 digit code)");
    814         }
    815 
    816         private void onTextChange() {
    817             String value = mText.getText();
    818 
    819             if (value.length() == 0) {
    820                 // empty string, means a qualifier with no value.
    821                 // Since the qualifier classes are immutable, and we don't want to
    822                 // remove the qualifier from the configuration, we create a new default one.
    823                 mSelectedConfiguration.setNetworkCodeQualifier(new NetworkCodeQualifier());
    824             } else {
    825                 try {
    826                     NetworkCodeQualifier qualifier = NetworkCodeQualifier.getQualifier(
    827                             NetworkCodeQualifier.getFolderSegment(Integer.parseInt(value)));
    828                     if (qualifier != null) {
    829                         mSelectedConfiguration.setNetworkCodeQualifier(qualifier);
    830                     } else {
    831                         // Failure! Looks like the value is wrong
    832                         // (for instance not exactly 3 digits).
    833                         mSelectedConfiguration.setNetworkCodeQualifier(new NetworkCodeQualifier());
    834                     }
    835                 } catch (NumberFormatException nfe) {
    836                     // Looks like the code is not a number. This should not happen since the text
    837                     // field has a VerifyListener that prevents it.
    838                     mSelectedConfiguration.setNetworkCodeQualifier(new NetworkCodeQualifier());
    839                 }
    840             }
    841 
    842             // notify of change
    843             onChange(true /* keepSelection */);
    844         }
    845 
    846         @Override
    847         public void setQualifier(ResourceQualifier qualifier) {
    848             NetworkCodeQualifier q = (NetworkCodeQualifier)qualifier;
    849 
    850             mText.setText(Integer.toString(q.getCode()));
    851         }
    852     }
    853 
    854     /**
    855      * Edit widget for {@link LanguageQualifier}.
    856      */
    857     private class LanguageEdit extends QualifierEditBase {
    858         private Combo mLanguage;
    859 
    860         public LanguageEdit(Composite parent) {
    861             super(parent, LanguageQualifier.NAME);
    862 
    863             mLanguage = new Combo(this, SWT.DROP_DOWN);
    864             mLanguage.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    865             mLanguage.addVerifyListener(new LanguageRegionVerifier());
    866             mLanguage.addSelectionListener(new SelectionListener() {
    867                 @Override
    868                 public void widgetDefaultSelected(SelectionEvent e) {
    869                     onLanguageChange();
    870                 }
    871                 @Override
    872                 public void widgetSelected(SelectionEvent e) {
    873                     onLanguageChange();
    874                 }
    875             });
    876             mLanguage.addModifyListener(new ModifyListener() {
    877                 @Override
    878                 public void modifyText(ModifyEvent e) {
    879                     onLanguageChange();
    880                 }
    881             });
    882 
    883             new Label(this, SWT.NONE).setText("(2 letter code)");
    884         }
    885 
    886         private void onLanguageChange() {
    887             // update the current config
    888             String value = mLanguage.getText();
    889 
    890             if (value.length() == 0) {
    891                 // empty string, means no qualifier.
    892                 // Since the qualifier classes are immutable, and we don't want to
    893                 // remove the qualifier from the configuration, we create a new default one.
    894                 mSelectedConfiguration.setLanguageQualifier(new LanguageQualifier());
    895             } else {
    896                 LanguageQualifier qualifier = null;
    897                 String segment = LanguageQualifier.getFolderSegment(value);
    898                 if (segment != null) {
    899                     qualifier = LanguageQualifier.getQualifier(segment);
    900                 }
    901 
    902                 if (qualifier != null) {
    903                     mSelectedConfiguration.setLanguageQualifier(qualifier);
    904                 } else {
    905                     // Failure! Looks like the value is wrong (for instance a one letter string).
    906                     mSelectedConfiguration.setLanguageQualifier(new LanguageQualifier());
    907                 }
    908             }
    909 
    910             // notify of change
    911             onChange(true /* keepSelection */);
    912         }
    913 
    914         @Override
    915         public void setQualifier(ResourceQualifier qualifier) {
    916             LanguageQualifier q = (LanguageQualifier)qualifier;
    917 
    918             String value = q.getValue();
    919             if (value != null) {
    920                 mLanguage.setText(value);
    921             }
    922         }
    923     }
    924 
    925     /**
    926      * Edit widget for {@link RegionQualifier}.
    927      */
    928     private class RegionEdit extends QualifierEditBase {
    929         private Combo mRegion;
    930 
    931         public RegionEdit(Composite parent) {
    932             super(parent, RegionQualifier.NAME);
    933 
    934             mRegion = new Combo(this, SWT.DROP_DOWN);
    935             mRegion.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
    936             mRegion.addVerifyListener(new LanguageRegionVerifier());
    937             mRegion.addSelectionListener(new SelectionListener() {
    938                 @Override
    939                 public void widgetDefaultSelected(SelectionEvent e) {
    940                     onRegionChange();
    941                 }
    942                 @Override
    943                 public void widgetSelected(SelectionEvent e) {
    944                     onRegionChange();
    945                 }
    946             });
    947             mRegion.addModifyListener(new ModifyListener() {
    948                 @Override
    949                 public void modifyText(ModifyEvent e) {
    950                     onRegionChange();
    951                 }
    952             });
    953 
    954             new Label(this, SWT.NONE).setText("(2 letter code)");
    955         }
    956 
    957         private void onRegionChange() {
    958             // update the current config
    959             String value = mRegion.getText();
    960 
    961             if (value.length() == 0) {
    962                 // empty string, means no qualifier.
    963                 // Since the qualifier classes are immutable, and we don't want to
    964                 // remove the qualifier from the configuration, we create a new default one.
    965                 mSelectedConfiguration.setRegionQualifier(new RegionQualifier());
    966             } else {
    967                 RegionQualifier qualifier = null;
    968                 String segment = RegionQualifier.getFolderSegment(value);
    969                 if (segment != null) {
    970                     qualifier = RegionQualifier.getQualifier(segment);
    971                 }
    972 
    973                 if (qualifier != null) {
    974                     mSelectedConfiguration.setRegionQualifier(qualifier);
    975                 } else {
    976                     // Failure! Looks like the value is wrong (for instance a one letter string).
    977                     mSelectedConfiguration.setRegionQualifier(new RegionQualifier());
    978                 }
    979             }
    980 
    981             // notify of change
    982             onChange(true /* keepSelection */);
    983         }
    984 
    985         @Override
    986         public void setQualifier(ResourceQualifier qualifier) {
    987             RegionQualifier q = (RegionQualifier)qualifier;
    988 
    989             String value = q.getValue();
    990             if (value != null) {
    991                 mRegion.setText(q.getValue());
    992             }
    993         }
    994     }
    995 
    996     /**
    997      * Edit widget for {@link SmallestScreenWidthQualifier}.
    998      */
    999     private class SmallestScreenWidthEdit extends QualifierEditBase {
   1000 
   1001         private Text mSize;
   1002 
   1003         public SmallestScreenWidthEdit(Composite parent) {
   1004             super(parent, SmallestScreenWidthQualifier.NAME);
   1005 
   1006             ModifyListener modifyListener = new ModifyListener() {
   1007                 @Override
   1008                 public void modifyText(ModifyEvent e) {
   1009                     onSizeChange();
   1010                 }
   1011             };
   1012 
   1013             FocusAdapter focusListener = new FocusAdapter() {
   1014                 @Override
   1015                 public void focusLost(FocusEvent e) {
   1016                     onSizeChange();
   1017                 }
   1018             };
   1019 
   1020             mSize = new Text(this, SWT.BORDER);
   1021             mSize.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1022             mSize.addVerifyListener(new DimensionVerifier());
   1023             mSize.addModifyListener(modifyListener);
   1024             mSize.addFocusListener(focusListener);
   1025         }
   1026 
   1027         private void onSizeChange() {
   1028             // update the current config
   1029             String size = mSize.getText();
   1030 
   1031             if (size.length() == 0) {
   1032                 // if one of the strings is empty, reset to no qualifier.
   1033                 // Since the qualifier classes are immutable, and we don't want to
   1034                 // remove the qualifier from the configuration, we create a new default one.
   1035                 mSelectedConfiguration.setSmallestScreenWidthQualifier(
   1036                         new SmallestScreenWidthQualifier());
   1037             } else {
   1038                 SmallestScreenWidthQualifier qualifier = SmallestScreenWidthQualifier.getQualifier(
   1039                         size);
   1040 
   1041                 if (qualifier != null) {
   1042                     mSelectedConfiguration.setSmallestScreenWidthQualifier(qualifier);
   1043                 } else {
   1044                     // Failure! Looks like the value is wrong, reset the qualifier
   1045                     // Since the qualifier classes are immutable, and we don't want to
   1046                     // remove the qualifier from the configuration, we create a new default one.
   1047                     mSelectedConfiguration.setSmallestScreenWidthQualifier(
   1048                             new SmallestScreenWidthQualifier());
   1049                 }
   1050             }
   1051 
   1052             // notify of change
   1053             onChange(true /* keepSelection */);
   1054         }
   1055 
   1056         @Override
   1057         public void setQualifier(ResourceQualifier qualifier) {
   1058             SmallestScreenWidthQualifier q = (SmallestScreenWidthQualifier)qualifier;
   1059 
   1060             mSize.setText(Integer.toString(q.getValue()));
   1061         }
   1062     }
   1063 
   1064     /**
   1065      * Edit widget for {@link ScreenWidthQualifier}.
   1066      */
   1067     private class ScreenWidthEdit extends QualifierEditBase {
   1068 
   1069         private Text mSize;
   1070 
   1071         public ScreenWidthEdit(Composite parent) {
   1072             super(parent, ScreenWidthQualifier.NAME);
   1073 
   1074             ModifyListener modifyListener = new ModifyListener() {
   1075                 @Override
   1076                 public void modifyText(ModifyEvent e) {
   1077                     onSizeChange();
   1078                 }
   1079             };
   1080 
   1081             FocusAdapter focusListener = new FocusAdapter() {
   1082                 @Override
   1083                 public void focusLost(FocusEvent e) {
   1084                     onSizeChange();
   1085                 }
   1086             };
   1087 
   1088             mSize = new Text(this, SWT.BORDER);
   1089             mSize.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1090             mSize.addVerifyListener(new DimensionVerifier());
   1091             mSize.addModifyListener(modifyListener);
   1092             mSize.addFocusListener(focusListener);
   1093         }
   1094 
   1095         private void onSizeChange() {
   1096             // update the current config
   1097             String size = mSize.getText();
   1098 
   1099             if (size.length() == 0) {
   1100                 // if one of the strings is empty, reset to no qualifier.
   1101                 // Since the qualifier classes are immutable, and we don't want to
   1102                 // remove the qualifier from the configuration, we create a new default one.
   1103                 mSelectedConfiguration.setScreenWidthQualifier(new ScreenWidthQualifier());
   1104             } else {
   1105                 ScreenWidthQualifier qualifier = ScreenWidthQualifier.getQualifier(size);
   1106 
   1107                 if (qualifier != null) {
   1108                     mSelectedConfiguration.setScreenWidthQualifier(qualifier);
   1109                 } else {
   1110                     // Failure! Looks like the value is wrong, reset the qualifier
   1111                     // Since the qualifier classes are immutable, and we don't want to
   1112                     // remove the qualifier from the configuration, we create a new default one.
   1113                     mSelectedConfiguration.setScreenWidthQualifier(
   1114                             new ScreenWidthQualifier());
   1115                 }
   1116             }
   1117 
   1118             // notify of change
   1119             onChange(true /* keepSelection */);
   1120         }
   1121 
   1122         @Override
   1123         public void setQualifier(ResourceQualifier qualifier) {
   1124             ScreenWidthQualifier q = (ScreenWidthQualifier)qualifier;
   1125 
   1126             mSize.setText(Integer.toString(q.getValue()));
   1127         }
   1128     }
   1129 
   1130     /**
   1131      * Edit widget for {@link ScreenHeightQualifier}.
   1132      */
   1133     private class ScreenHeightEdit extends QualifierEditBase {
   1134 
   1135         private Text mSize;
   1136 
   1137         public ScreenHeightEdit(Composite parent) {
   1138             super(parent, ScreenHeightQualifier.NAME);
   1139 
   1140             ModifyListener modifyListener = new ModifyListener() {
   1141                 @Override
   1142                 public void modifyText(ModifyEvent e) {
   1143                     onSizeChange();
   1144                 }
   1145             };
   1146 
   1147             FocusAdapter focusListener = new FocusAdapter() {
   1148                 @Override
   1149                 public void focusLost(FocusEvent e) {
   1150                     onSizeChange();
   1151                 }
   1152             };
   1153 
   1154             mSize = new Text(this, SWT.BORDER);
   1155             mSize.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1156             mSize.addVerifyListener(new DimensionVerifier());
   1157             mSize.addModifyListener(modifyListener);
   1158             mSize.addFocusListener(focusListener);
   1159         }
   1160 
   1161         private void onSizeChange() {
   1162             // update the current config
   1163             String size = mSize.getText();
   1164 
   1165             if (size.length() == 0) {
   1166                 // if one of the strings is empty, reset to no qualifier.
   1167                 // Since the qualifier classes are immutable, and we don't want to
   1168                 // remove the qualifier from the configuration, we create a new default one.
   1169                 mSelectedConfiguration.setScreenHeightQualifier(new ScreenHeightQualifier());
   1170             } else {
   1171                 ScreenHeightQualifier qualifier = ScreenHeightQualifier.getQualifier(size);
   1172 
   1173                 if (qualifier != null) {
   1174                     mSelectedConfiguration.setScreenHeightQualifier(qualifier);
   1175                 } else {
   1176                     // Failure! Looks like the value is wrong, reset the qualifier
   1177                     // Since the qualifier classes are immutable, and we don't want to
   1178                     // remove the qualifier from the configuration, we create a new default one.
   1179                     mSelectedConfiguration.setScreenHeightQualifier(
   1180                             new ScreenHeightQualifier());
   1181                 }
   1182             }
   1183 
   1184             // notify of change
   1185             onChange(true /* keepSelection */);
   1186         }
   1187 
   1188         @Override
   1189         public void setQualifier(ResourceQualifier qualifier) {
   1190             ScreenHeightQualifier q = (ScreenHeightQualifier)qualifier;
   1191 
   1192             mSize.setText(Integer.toString(q.getValue()));
   1193         }
   1194     }
   1195 
   1196 
   1197     /**
   1198      * Edit widget for {@link ScreenSizeQualifier}.
   1199      */
   1200     private class ScreenSizeEdit extends QualifierEditBase {
   1201 
   1202         private Combo mSize;
   1203 
   1204         public ScreenSizeEdit(Composite parent) {
   1205             super(parent, ScreenSizeQualifier.NAME);
   1206 
   1207             mSize = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
   1208             fillCombo(mSize, ScreenSize.values());
   1209 
   1210             mSize.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1211             mSize.addSelectionListener(new SelectionListener() {
   1212                 @Override
   1213                 public void widgetDefaultSelected(SelectionEvent e) {
   1214                     onScreenSizeChange();
   1215                 }
   1216                 @Override
   1217                 public void widgetSelected(SelectionEvent e) {
   1218                     onScreenSizeChange();
   1219                 }
   1220             });
   1221         }
   1222 
   1223         protected void onScreenSizeChange() {
   1224             // update the current config
   1225             int index = mSize.getSelectionIndex();
   1226 
   1227             if (index != -1) {
   1228                 mSelectedConfiguration.setScreenSizeQualifier(new ScreenSizeQualifier(
   1229                         ScreenSize.getByIndex(index)));
   1230             } else {
   1231                 // empty selection, means no qualifier.
   1232                 // Since the qualifier classes are immutable, and we don't want to
   1233                 // remove the qualifier from the configuration, we create a new default one.
   1234                 mSelectedConfiguration.setScreenSizeQualifier(
   1235                         new ScreenSizeQualifier());
   1236             }
   1237 
   1238             // notify of change
   1239             onChange(true /* keepSelection */);
   1240         }
   1241 
   1242         @Override
   1243         public void setQualifier(ResourceQualifier qualifier) {
   1244             ScreenSizeQualifier q = (ScreenSizeQualifier)qualifier;
   1245 
   1246             ScreenSize value = q.getValue();
   1247             if (value == null) {
   1248                 mSize.clearSelection();
   1249             } else {
   1250                 mSize.select(ScreenSize.getIndex(value));
   1251             }
   1252         }
   1253     }
   1254 
   1255     /**
   1256      * Edit widget for {@link ScreenRatioQualifier}.
   1257      */
   1258     private class ScreenRatioEdit extends QualifierEditBase {
   1259 
   1260         private Combo mRatio;
   1261 
   1262         public ScreenRatioEdit(Composite parent) {
   1263             super(parent, ScreenRatioQualifier.NAME);
   1264 
   1265             mRatio = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
   1266             fillCombo(mRatio, ScreenRatio.values());
   1267 
   1268             mRatio.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1269             mRatio.addSelectionListener(new SelectionListener() {
   1270                 @Override
   1271                 public void widgetDefaultSelected(SelectionEvent e) {
   1272                     onScreenRatioChange();
   1273                 }
   1274                 @Override
   1275                 public void widgetSelected(SelectionEvent e) {
   1276                     onScreenRatioChange();
   1277                 }
   1278             });
   1279         }
   1280 
   1281         protected void onScreenRatioChange() {
   1282             // update the current config
   1283             int index = mRatio.getSelectionIndex();
   1284 
   1285             if (index != -1) {
   1286                 mSelectedConfiguration.setScreenRatioQualifier(new ScreenRatioQualifier(
   1287                         ScreenRatio.getByIndex(index)));
   1288             } else {
   1289                 // empty selection, means no qualifier.
   1290                 // Since the qualifier classes are immutable, and we don't want to
   1291                 // remove the qualifier from the configuration, we create a new default one.
   1292                 mSelectedConfiguration.setScreenRatioQualifier(
   1293                         new ScreenRatioQualifier());
   1294             }
   1295 
   1296             // notify of change
   1297             onChange(true /* keepSelection */);
   1298         }
   1299 
   1300         @Override
   1301         public void setQualifier(ResourceQualifier qualifier) {
   1302             ScreenRatioQualifier q = (ScreenRatioQualifier)qualifier;
   1303 
   1304             ScreenRatio value = q.getValue();
   1305             if (value == null) {
   1306                 mRatio.clearSelection();
   1307             } else {
   1308                 mRatio.select(ScreenRatio.getIndex(value));
   1309             }
   1310         }
   1311     }
   1312 
   1313     /**
   1314      * Edit widget for {@link ScreenOrientationQualifier}.
   1315      */
   1316     private class OrientationEdit extends QualifierEditBase {
   1317 
   1318         private Combo mOrientation;
   1319 
   1320         public OrientationEdit(Composite parent) {
   1321             super(parent, ScreenOrientationQualifier.NAME);
   1322 
   1323             mOrientation = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
   1324             fillCombo(mOrientation, ScreenOrientation.values());
   1325 
   1326             mOrientation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1327             mOrientation.addSelectionListener(new SelectionListener() {
   1328                 @Override
   1329                 public void widgetDefaultSelected(SelectionEvent e) {
   1330                     onOrientationChange();
   1331                 }
   1332                 @Override
   1333                 public void widgetSelected(SelectionEvent e) {
   1334                     onOrientationChange();
   1335                 }
   1336             });
   1337         }
   1338 
   1339         protected void onOrientationChange() {
   1340             // update the current config
   1341             int index = mOrientation.getSelectionIndex();
   1342 
   1343             if (index != -1) {
   1344                 mSelectedConfiguration.setScreenOrientationQualifier(new ScreenOrientationQualifier(
   1345                     ScreenOrientation.getByIndex(index)));
   1346             } else {
   1347                 // empty selection, means no qualifier.
   1348                 // Since the qualifier classes are immutable, and we don't want to
   1349                 // remove the qualifier from the configuration, we create a new default one.
   1350                 mSelectedConfiguration.setScreenOrientationQualifier(
   1351                         new ScreenOrientationQualifier());
   1352             }
   1353 
   1354             // notify of change
   1355             onChange(true /* keepSelection */);
   1356         }
   1357 
   1358         @Override
   1359         public void setQualifier(ResourceQualifier qualifier) {
   1360             ScreenOrientationQualifier q = (ScreenOrientationQualifier)qualifier;
   1361 
   1362             ScreenOrientation value = q.getValue();
   1363             if (value == null) {
   1364                 mOrientation.clearSelection();
   1365             } else {
   1366                 mOrientation.select(ScreenOrientation.getIndex(value));
   1367             }
   1368         }
   1369     }
   1370 
   1371     /**
   1372      * Edit widget for {@link DockModeQualifier}.
   1373      */
   1374     private class UiModeEdit extends QualifierEditBase {
   1375 
   1376         private Combo mUiMode;
   1377 
   1378         public UiModeEdit(Composite parent) {
   1379             super(parent, UiModeQualifier.NAME);
   1380 
   1381             mUiMode = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
   1382             fillCombo(mUiMode, UiMode.values());
   1383 
   1384             mUiMode.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1385             mUiMode.addSelectionListener(new SelectionListener() {
   1386                 @Override
   1387                 public void widgetDefaultSelected(SelectionEvent e) {
   1388                     onDockModeChange();
   1389                 }
   1390                 @Override
   1391                 public void widgetSelected(SelectionEvent e) {
   1392                     onDockModeChange();
   1393                 }
   1394             });
   1395         }
   1396 
   1397         protected void onDockModeChange() {
   1398             // update the current config
   1399             int index = mUiMode.getSelectionIndex();
   1400 
   1401             if (index != -1) {
   1402                 mSelectedConfiguration.setUiModeQualifier(
   1403                         new UiModeQualifier(UiMode.getByIndex(index)));
   1404             } else {
   1405                 // empty selection, means no qualifier.
   1406                 // Since the qualifier classes are immutable, and we don't want to
   1407                 // remove the qualifier from the configuration, we create a new default one.
   1408                 mSelectedConfiguration.setUiModeQualifier(new UiModeQualifier());
   1409             }
   1410 
   1411             // notify of change
   1412             onChange(true /* keepSelection */);
   1413         }
   1414 
   1415         @Override
   1416         public void setQualifier(ResourceQualifier qualifier) {
   1417             UiModeQualifier q = (UiModeQualifier)qualifier;
   1418 
   1419             UiMode value = q.getValue();
   1420             if (value == null) {
   1421                 mUiMode.clearSelection();
   1422             } else {
   1423                 mUiMode.select(UiMode.getIndex(value));
   1424             }
   1425         }
   1426     }
   1427 
   1428     /**
   1429      * Edit widget for {@link NightModeQualifier}.
   1430      */
   1431     private class NightModeEdit extends QualifierEditBase {
   1432 
   1433         private Combo mNightMode;
   1434 
   1435         public NightModeEdit(Composite parent) {
   1436             super(parent, NightModeQualifier.NAME);
   1437 
   1438             mNightMode = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
   1439             fillCombo(mNightMode, NightMode.values());
   1440 
   1441             mNightMode.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1442             mNightMode.addSelectionListener(new SelectionListener() {
   1443                 @Override
   1444                 public void widgetDefaultSelected(SelectionEvent e) {
   1445                     onNightModeChange();
   1446                 }
   1447                 @Override
   1448                 public void widgetSelected(SelectionEvent e) {
   1449                     onNightModeChange();
   1450                 }
   1451             });
   1452         }
   1453 
   1454         protected void onNightModeChange() {
   1455             // update the current config
   1456             int index = mNightMode.getSelectionIndex();
   1457 
   1458             if (index != -1) {
   1459                 mSelectedConfiguration.setNightModeQualifier(
   1460                         new NightModeQualifier(NightMode.getByIndex(index)));
   1461             } else {
   1462                 // empty selection, means no qualifier.
   1463                 // Since the qualifier classes are immutable, and we don't want to
   1464                 // remove the qualifier from the configuration, we create a new default one.
   1465                 mSelectedConfiguration.setNightModeQualifier(new NightModeQualifier());
   1466             }
   1467 
   1468             // notify of change
   1469             onChange(true /* keepSelection */);
   1470         }
   1471 
   1472         @Override
   1473         public void setQualifier(ResourceQualifier qualifier) {
   1474             NightModeQualifier q = (NightModeQualifier)qualifier;
   1475 
   1476             NightMode value = q.getValue();
   1477             if (value == null) {
   1478                 mNightMode.clearSelection();
   1479             } else {
   1480                 mNightMode.select(NightMode.getIndex(value));
   1481             }
   1482         }
   1483     }
   1484 
   1485 
   1486     /**
   1487      * Edit widget for {@link DensityQualifier}.
   1488      */
   1489     private class DensityEdit extends QualifierEditBase {
   1490         private Combo mDensity;
   1491 
   1492         public DensityEdit(Composite parent) {
   1493             super(parent, DensityQualifier.NAME);
   1494 
   1495             mDensity = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
   1496             fillCombo(mDensity, Density.values());
   1497 
   1498             mDensity.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1499             mDensity.addSelectionListener(new SelectionListener() {
   1500                 @Override
   1501                 public void widgetDefaultSelected(SelectionEvent e) {
   1502                     onDensityChange();
   1503                 }
   1504                 @Override
   1505                 public void widgetSelected(SelectionEvent e) {
   1506                     onDensityChange();
   1507                 }
   1508             });
   1509         }
   1510 
   1511         private void onDensityChange() {
   1512             // update the current config
   1513             int index = mDensity.getSelectionIndex();
   1514 
   1515             if (index != -1) {
   1516                 mSelectedConfiguration.setDensityQualifier(new DensityQualifier(
   1517                     Density.getByIndex(index)));
   1518             } else {
   1519                 // empty selection, means no qualifier.
   1520                 // Since the qualifier classes are immutable, and we don't want to
   1521                 // remove the qualifier from the configuration, we create a new default one.
   1522                 mSelectedConfiguration.setDensityQualifier(
   1523                         new DensityQualifier());
   1524             }
   1525 
   1526             // notify of change
   1527             onChange(true /* keepSelection */);
   1528         }
   1529 
   1530         @Override
   1531         public void setQualifier(ResourceQualifier qualifier) {
   1532             DensityQualifier q = (DensityQualifier)qualifier;
   1533 
   1534             Density value = q.getValue();
   1535             if (value == null) {
   1536                 mDensity.clearSelection();
   1537             } else {
   1538                 mDensity.select(Density.getIndex(value));
   1539             }
   1540         }
   1541     }
   1542 
   1543     /**
   1544      * Edit widget for {@link TouchScreenQualifier}.
   1545      */
   1546     private class TouchEdit extends QualifierEditBase {
   1547 
   1548         private Combo mTouchScreen;
   1549 
   1550         public TouchEdit(Composite parent) {
   1551             super(parent, TouchScreenQualifier.NAME);
   1552 
   1553             mTouchScreen = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
   1554             fillCombo(mTouchScreen, TouchScreen.values());
   1555 
   1556             mTouchScreen.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1557             mTouchScreen.addSelectionListener(new SelectionListener() {
   1558                 @Override
   1559                 public void widgetDefaultSelected(SelectionEvent e) {
   1560                     onTouchChange();
   1561                 }
   1562                 @Override
   1563                 public void widgetSelected(SelectionEvent e) {
   1564                     onTouchChange();
   1565                 }
   1566             });
   1567         }
   1568 
   1569         protected void onTouchChange() {
   1570             // update the current config
   1571             int index = mTouchScreen.getSelectionIndex();
   1572 
   1573             if (index != -1) {
   1574                 mSelectedConfiguration.setTouchTypeQualifier(new TouchScreenQualifier(
   1575                         TouchScreen.getByIndex(index)));
   1576             } else {
   1577                 // empty selection, means no qualifier.
   1578                 // Since the qualifier classes are immutable, and we don't want to
   1579                 // remove the qualifier from the configuration, we create a new default one.
   1580                 mSelectedConfiguration.setTouchTypeQualifier(new TouchScreenQualifier());
   1581             }
   1582 
   1583             // notify of change
   1584             onChange(true /* keepSelection */);
   1585         }
   1586 
   1587         @Override
   1588         public void setQualifier(ResourceQualifier qualifier) {
   1589             TouchScreenQualifier q = (TouchScreenQualifier)qualifier;
   1590 
   1591             TouchScreen value = q.getValue();
   1592             if (value == null) {
   1593                 mTouchScreen.clearSelection();
   1594             } else {
   1595                 mTouchScreen.select(TouchScreen.getIndex(value));
   1596             }
   1597         }
   1598     }
   1599 
   1600     /**
   1601      * Edit widget for {@link KeyboardStateQualifier}.
   1602      */
   1603     private class KeyboardEdit extends QualifierEditBase {
   1604 
   1605         private Combo mKeyboardState;
   1606 
   1607         public KeyboardEdit(Composite parent) {
   1608             super(parent, KeyboardStateQualifier.NAME);
   1609 
   1610             mKeyboardState = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
   1611             fillCombo(mKeyboardState, KeyboardState.values());
   1612 
   1613             mKeyboardState.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1614             mKeyboardState.addSelectionListener(new SelectionListener() {
   1615                 @Override
   1616                 public void widgetDefaultSelected(SelectionEvent e) {
   1617                     onKeyboardChange();
   1618                 }
   1619                 @Override
   1620                 public void widgetSelected(SelectionEvent e) {
   1621                     onKeyboardChange();
   1622                 }
   1623             });
   1624         }
   1625 
   1626         protected void onKeyboardChange() {
   1627             // update the current config
   1628             int index = mKeyboardState.getSelectionIndex();
   1629 
   1630             if (index != -1) {
   1631                 mSelectedConfiguration.setKeyboardStateQualifier(new KeyboardStateQualifier(
   1632                         KeyboardState.getByIndex(index)));
   1633             } else {
   1634                 // empty selection, means no qualifier.
   1635                 // Since the qualifier classes are immutable, and we don't want to
   1636                 // remove the qualifier from the configuration, we create a new default one.
   1637                 mSelectedConfiguration.setKeyboardStateQualifier(
   1638                         new KeyboardStateQualifier());
   1639             }
   1640 
   1641             // notify of change
   1642             onChange(true /* keepSelection */);
   1643         }
   1644 
   1645         @Override
   1646         public void setQualifier(ResourceQualifier qualifier) {
   1647             KeyboardStateQualifier q = (KeyboardStateQualifier)qualifier;
   1648 
   1649             KeyboardState value = q.getValue();
   1650             if (value == null) {
   1651                 mKeyboardState.clearSelection();
   1652             } else {
   1653                 mKeyboardState.select(KeyboardState.getIndex(value));
   1654             }
   1655         }
   1656     }
   1657 
   1658     /**
   1659      * Edit widget for {@link TextInputMethodQualifier}.
   1660      */
   1661     private class TextInputEdit extends QualifierEditBase {
   1662 
   1663         private Combo mTextInput;
   1664 
   1665         public TextInputEdit(Composite parent) {
   1666             super(parent, TextInputMethodQualifier.NAME);
   1667 
   1668             mTextInput = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
   1669             fillCombo(mTextInput, Keyboard.values());
   1670 
   1671             mTextInput.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1672             mTextInput.addSelectionListener(new SelectionListener() {
   1673                 @Override
   1674                 public void widgetDefaultSelected(SelectionEvent e) {
   1675                     onTextInputChange();
   1676                 }
   1677                 @Override
   1678                 public void widgetSelected(SelectionEvent e) {
   1679                     onTextInputChange();
   1680                 }
   1681             });
   1682         }
   1683 
   1684         protected void onTextInputChange() {
   1685             // update the current config
   1686             int index = mTextInput.getSelectionIndex();
   1687 
   1688             if (index != -1) {
   1689                 mSelectedConfiguration.setTextInputMethodQualifier(new TextInputMethodQualifier(
   1690                         Keyboard.getByIndex(index)));
   1691             } else {
   1692                 // empty selection, means no qualifier.
   1693                 // Since the qualifier classes are immutable, and we don't want to
   1694                 // remove the qualifier from the configuration, we create a new default one.
   1695                 mSelectedConfiguration.setTextInputMethodQualifier(
   1696                         new TextInputMethodQualifier());
   1697             }
   1698 
   1699             // notify of change
   1700             onChange(true /* keepSelection */);
   1701         }
   1702 
   1703         @Override
   1704         public void setQualifier(ResourceQualifier qualifier) {
   1705             TextInputMethodQualifier q = (TextInputMethodQualifier)qualifier;
   1706 
   1707             Keyboard value = q.getValue();
   1708             if (value == null) {
   1709                 mTextInput.clearSelection();
   1710             } else {
   1711                 mTextInput.select(Keyboard.getIndex(value));
   1712             }
   1713         }
   1714     }
   1715 
   1716     /**
   1717      * Edit widget for {@link NavigationStateQualifier}.
   1718      */
   1719     private class NavigationStateEdit extends QualifierEditBase {
   1720 
   1721         private Combo mNavigationState;
   1722 
   1723         public NavigationStateEdit(Composite parent) {
   1724             super(parent, NavigationStateQualifier.NAME);
   1725 
   1726             mNavigationState = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
   1727             fillCombo(mNavigationState, NavigationState.values());
   1728 
   1729             mNavigationState.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1730             mNavigationState.addSelectionListener(new SelectionListener() {
   1731                 @Override
   1732                 public void widgetDefaultSelected(SelectionEvent e) {
   1733                     onNavigationChange();
   1734                 }
   1735                 @Override
   1736                 public void widgetSelected(SelectionEvent e) {
   1737                     onNavigationChange();
   1738                 }
   1739             });
   1740         }
   1741 
   1742         protected void onNavigationChange() {
   1743             // update the current config
   1744             int index = mNavigationState.getSelectionIndex();
   1745 
   1746             if (index != -1) {
   1747                 mSelectedConfiguration.setNavigationStateQualifier(
   1748                         new NavigationStateQualifier(NavigationState.getByIndex(index)));
   1749             } else {
   1750                 // empty selection, means no qualifier.
   1751                 // Since the qualifier classes are immutable, and we don't want to
   1752                 // remove the qualifier from the configuration, we create a new default one.
   1753                 mSelectedConfiguration.setNavigationStateQualifier(new NavigationStateQualifier());
   1754             }
   1755 
   1756             // notify of change
   1757             onChange(true /* keepSelection */);
   1758         }
   1759 
   1760         @Override
   1761         public void setQualifier(ResourceQualifier qualifier) {
   1762             NavigationStateQualifier q = (NavigationStateQualifier)qualifier;
   1763 
   1764             NavigationState value = q.getValue();
   1765             if (value == null) {
   1766                 mNavigationState.clearSelection();
   1767             } else {
   1768                 mNavigationState.select(NavigationState.getIndex(value));
   1769             }
   1770         }
   1771     }
   1772 
   1773 
   1774     /**
   1775      * Edit widget for {@link NavigationMethodQualifier}.
   1776      */
   1777     private class NavigationEdit extends QualifierEditBase {
   1778 
   1779         private Combo mNavigation;
   1780 
   1781         public NavigationEdit(Composite parent) {
   1782             super(parent, NavigationMethodQualifier.NAME);
   1783 
   1784             mNavigation = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
   1785             fillCombo(mNavigation, Navigation.values());
   1786 
   1787             mNavigation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1788             mNavigation.addSelectionListener(new SelectionListener() {
   1789                 @Override
   1790                 public void widgetDefaultSelected(SelectionEvent e) {
   1791                     onNavigationChange();
   1792                 }
   1793                 @Override
   1794                 public void widgetSelected(SelectionEvent e) {
   1795                     onNavigationChange();
   1796                 }
   1797             });
   1798         }
   1799 
   1800         protected void onNavigationChange() {
   1801             // update the current config
   1802             int index = mNavigation.getSelectionIndex();
   1803 
   1804             if (index != -1) {
   1805                 mSelectedConfiguration.setNavigationMethodQualifier(new NavigationMethodQualifier(
   1806                         Navigation.getByIndex(index)));
   1807             } else {
   1808                 // empty selection, means no qualifier.
   1809                 // Since the qualifier classes are immutable, and we don't want to
   1810                 // remove the qualifier from the configuration, we create a new default one.
   1811                 mSelectedConfiguration.setNavigationMethodQualifier(
   1812                         new NavigationMethodQualifier());
   1813             }
   1814 
   1815             // notify of change
   1816             onChange(true /* keepSelection */);
   1817         }
   1818 
   1819         @Override
   1820         public void setQualifier(ResourceQualifier qualifier) {
   1821             NavigationMethodQualifier q = (NavigationMethodQualifier)qualifier;
   1822 
   1823             Navigation value = q.getValue();
   1824             if (value == null) {
   1825                 mNavigation.clearSelection();
   1826             } else {
   1827                 mNavigation.select(Navigation.getIndex(value));
   1828             }
   1829         }
   1830     }
   1831 
   1832     /**
   1833      * Edit widget for {@link ScreenDimensionQualifier}.
   1834      */
   1835     private class ScreenDimensionEdit extends QualifierEditBase {
   1836 
   1837         private Text mSize1;
   1838         private Text mSize2;
   1839 
   1840         public ScreenDimensionEdit(Composite parent) {
   1841             super(parent, ScreenDimensionQualifier.NAME);
   1842 
   1843             ModifyListener modifyListener = new ModifyListener() {
   1844                 @Override
   1845                 public void modifyText(ModifyEvent e) {
   1846                     onSizeChange();
   1847                 }
   1848             };
   1849 
   1850             FocusAdapter focusListener = new FocusAdapter() {
   1851                 @Override
   1852                 public void focusLost(FocusEvent e) {
   1853                     onSizeChange();
   1854                 }
   1855             };
   1856 
   1857             mSize1 = new Text(this, SWT.BORDER);
   1858             mSize1.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1859             mSize1.addVerifyListener(new DimensionVerifier());
   1860             mSize1.addModifyListener(modifyListener);
   1861             mSize1.addFocusListener(focusListener);
   1862 
   1863             mSize2 = new Text(this, SWT.BORDER);
   1864             mSize2.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1865             mSize2.addVerifyListener(new DimensionVerifier());
   1866             mSize2.addModifyListener(modifyListener);
   1867             mSize2.addFocusListener(focusListener);
   1868         }
   1869 
   1870         private void onSizeChange() {
   1871             // update the current config
   1872             String size1 = mSize1.getText();
   1873             String size2 = mSize2.getText();
   1874 
   1875             if (size1.length() == 0 || size2.length() == 0) {
   1876                 // if one of the strings is empty, reset to no qualifier.
   1877                 // Since the qualifier classes are immutable, and we don't want to
   1878                 // remove the qualifier from the configuration, we create a new default one.
   1879                 mSelectedConfiguration.setScreenDimensionQualifier(new ScreenDimensionQualifier());
   1880             } else {
   1881                 ScreenDimensionQualifier qualifier = ScreenDimensionQualifier.getQualifier(size1,
   1882                         size2);
   1883 
   1884                 if (qualifier != null) {
   1885                     mSelectedConfiguration.setScreenDimensionQualifier(qualifier);
   1886                 } else {
   1887                     // Failure! Looks like the value is wrong, reset the qualifier
   1888                     // Since the qualifier classes are immutable, and we don't want to
   1889                     // remove the qualifier from the configuration, we create a new default one.
   1890                     mSelectedConfiguration.setScreenDimensionQualifier(
   1891                             new ScreenDimensionQualifier());
   1892                 }
   1893             }
   1894 
   1895             // notify of change
   1896             onChange(true /* keepSelection */);
   1897         }
   1898 
   1899         @Override
   1900         public void setQualifier(ResourceQualifier qualifier) {
   1901             ScreenDimensionQualifier q = (ScreenDimensionQualifier)qualifier;
   1902 
   1903             mSize1.setText(Integer.toString(q.getValue1()));
   1904             mSize2.setText(Integer.toString(q.getValue2()));
   1905         }
   1906     }
   1907 
   1908     /**
   1909      * Edit widget for {@link VersionQualifier}.
   1910      */
   1911     private class VersionEdit extends QualifierEditBase {
   1912         private Text mText;
   1913 
   1914         public VersionEdit(Composite parent) {
   1915             super(parent, VersionQualifier.NAME);
   1916 
   1917             mText = new Text(this, SWT.BORDER);
   1918             mText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
   1919             mText.addVerifyListener(new MobileCodeVerifier());
   1920             mText.addModifyListener(new ModifyListener() {
   1921                 @Override
   1922                 public void modifyText(ModifyEvent e) {
   1923                     onVersionChange();
   1924                 }
   1925             });
   1926             mText.addFocusListener(new FocusAdapter() {
   1927                 @Override
   1928                 public void focusLost(FocusEvent e) {
   1929                     onVersionChange();
   1930                 }
   1931             });
   1932 
   1933             new Label(this, SWT.NONE).setText("(Platform API level)");
   1934         }
   1935 
   1936         private void onVersionChange() {
   1937             String value = mText.getText();
   1938 
   1939             if (value.length() == 0) {
   1940                 // empty string, means a qualifier with no value.
   1941                 // Since the qualifier classes are immutable, and we don't want to
   1942                 // remove the qualifier from the configuration, we create a new default one.
   1943                 mSelectedConfiguration.setVersionQualifier(new VersionQualifier());
   1944             } else {
   1945                 try {
   1946                     VersionQualifier qualifier = VersionQualifier.getQualifier(
   1947                             VersionQualifier.getFolderSegment(Integer.parseInt(value)));
   1948                     if (qualifier != null) {
   1949                         mSelectedConfiguration.setVersionQualifier(qualifier);
   1950                     } else {
   1951                         // Failure! Looks like the value is wrong
   1952                         mSelectedConfiguration.setVersionQualifier(new VersionQualifier());
   1953                     }
   1954                 } catch (NumberFormatException nfe) {
   1955                     // Looks like the code is not a number. This should not happen since the text
   1956                     // field has a VerifyListener that prevents it.
   1957                     mSelectedConfiguration.setVersionQualifier(new VersionQualifier());
   1958                 }
   1959             }
   1960 
   1961             // notify of change
   1962             onChange(true /* keepSelection */);
   1963         }
   1964 
   1965         @Override
   1966         public void setQualifier(ResourceQualifier qualifier) {
   1967             VersionQualifier q = (VersionQualifier)qualifier;
   1968 
   1969             mText.setText(Integer.toString(q.getVersion()));
   1970         }
   1971     }
   1972 
   1973 }
   1974