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