• 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.ide.eclipse.adt.internal.resources.configurations.CountryCodeQualifier;
20 import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
21 import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier;
22 import com.android.ide.eclipse.adt.internal.resources.configurations.LanguageQualifier;
23 import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier;
24 import com.android.ide.eclipse.adt.internal.resources.configurations.NetworkCodeQualifier;
25 import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier;
26 import com.android.ide.eclipse.adt.internal.resources.configurations.RegionQualifier;
27 import com.android.ide.eclipse.adt.internal.resources.configurations.ResourceQualifier;
28 import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenDimensionQualifier;
29 import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier;
30 import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier;
31 import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier;
32 import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier;
33 import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier;
34 import com.android.ide.eclipse.adt.internal.resources.configurations.VersionQualifier;
35 import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier.KeyboardState;
36 import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier.NavigationMethod;
37 import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier.Density;
38 import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier.ScreenOrientation;
39 import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier.ScreenRatio;
40 import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier.ScreenSize;
41 import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier.TextInputMethod;
42 import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier.TouchScreenType;
43 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
44 
45 import org.eclipse.jface.viewers.ILabelProviderListener;
46 import org.eclipse.jface.viewers.ISelection;
47 import org.eclipse.jface.viewers.ISelectionChangedListener;
48 import org.eclipse.jface.viewers.IStructuredContentProvider;
49 import org.eclipse.jface.viewers.IStructuredSelection;
50 import org.eclipse.jface.viewers.ITableLabelProvider;
51 import org.eclipse.jface.viewers.SelectionChangedEvent;
52 import org.eclipse.jface.viewers.StructuredSelection;
53 import org.eclipse.jface.viewers.TableViewer;
54 import org.eclipse.jface.viewers.Viewer;
55 import org.eclipse.swt.SWT;
56 import org.eclipse.swt.custom.StackLayout;
57 import org.eclipse.swt.events.ControlAdapter;
58 import org.eclipse.swt.events.ControlEvent;
59 import org.eclipse.swt.events.FocusAdapter;
60 import org.eclipse.swt.events.FocusEvent;
61 import org.eclipse.swt.events.ModifyEvent;
62 import org.eclipse.swt.events.ModifyListener;
63 import org.eclipse.swt.events.SelectionAdapter;
64 import org.eclipse.swt.events.SelectionEvent;
65 import org.eclipse.swt.events.SelectionListener;
66 import org.eclipse.swt.events.VerifyEvent;
67 import org.eclipse.swt.events.VerifyListener;
68 import org.eclipse.swt.graphics.Image;
69 import org.eclipse.swt.graphics.Rectangle;
70 import org.eclipse.swt.layout.GridData;
71 import org.eclipse.swt.layout.GridLayout;
72 import org.eclipse.swt.widgets.Button;
73 import org.eclipse.swt.widgets.Combo;
74 import org.eclipse.swt.widgets.Composite;
75 import org.eclipse.swt.widgets.Label;
76 import org.eclipse.swt.widgets.Table;
77 import org.eclipse.swt.widgets.TableColumn;
78 import org.eclipse.swt.widgets.Text;
79 
80 import java.util.ArrayList;
81 import java.util.HashMap;
82 
83 /**
84  * Custom UI widget to let user build a Folder configuration.
85  * <p/>
86  * To use this, instantiate somewhere in the UI and then:
87  * <ul>
88  * <li>Use {@link #setConfiguration(String)} or {@link #setConfiguration(FolderConfiguration)}.
89  * <li>Retrieve the configuration using {@link #getConfiguration(FolderConfiguration)}.
90  * </ul>
91  */
92 public class ConfigurationSelector extends Composite {
93 
94     public static final int WIDTH_HINT = 600;
95     public static final int HEIGHT_HINT = 250;
96 
97     private Runnable mOnChangeListener;
98 
99     private TableViewer mFullTableViewer;
100     private TableViewer mSelectionTableViewer;
101     private Button mAddButton;
102     private Button mRemoveButton;
103     private StackLayout mStackLayout;
104 
105     private boolean mOnRefresh = false;
106 
107     private final FolderConfiguration mBaseConfiguration = new FolderConfiguration();
108     private final FolderConfiguration mSelectedConfiguration = new FolderConfiguration();
109 
110     private final HashMap<Class<? extends ResourceQualifier>, QualifierEditBase> mUiMap =
111         new HashMap<Class<? extends ResourceQualifier>, QualifierEditBase>();
112     private final boolean mDeviceMode;
113     private Composite mQualifierEditParent;
114     private IQualifierFilter mQualifierFilter;
115 
116     /**
117      * Basic of {@link VerifyListener} to only accept digits.
118      */
119     private static class DigitVerifier implements VerifyListener {
verifyText(VerifyEvent e)120         public void verifyText(VerifyEvent e) {
121             // check for digit only.
122             for (int i = 0 ; i < e.text.length(); i++) {
123                 char letter = e.text.charAt(i);
124                 if (letter < '0' || letter > '9') {
125                     e.doit = false;
126                     return;
127                 }
128             }
129         }
130     }
131 
132     /**
133      * Implementation of {@link VerifyListener} for Country Code qualifiers.
134      */
135     public static class MobileCodeVerifier extends DigitVerifier {
136         @Override
verifyText(VerifyEvent e)137         public void verifyText(VerifyEvent e) {
138             super.verifyText(e);
139 
140             // basic tests passed?
141             if (e.doit) {
142                 // check the max 3 digits.
143                 if (e.text.length() - e.end + e.start +
144                         ((Text)e.getSource()).getText().length() > 3) {
145                     e.doit = false;
146                 }
147             }
148         }
149     }
150 
151     /**
152      * Implementation of {@link VerifyListener} for the Language and Region qualifiers.
153      */
154     public static class LanguageRegionVerifier implements VerifyListener {
verifyText(VerifyEvent e)155         public void verifyText(VerifyEvent e) {
156             // check for length
157             if (e.text.length() - e.end + e.start + ((Combo)e.getSource()).getText().length() > 2) {
158                 e.doit = false;
159                 return;
160             }
161 
162             // check for lower case only.
163             for (int i = 0 ; i < e.text.length(); i++) {
164                 char letter = e.text.charAt(i);
165                 if ((letter < 'a' || letter > 'z') && (letter < 'A' || letter > 'Z')) {
166                     e.doit = false;
167                     return;
168                 }
169             }
170         }
171     }
172 
173     /**
174      * Implementation of {@link VerifyListener} for the Pixel Density qualifier.
175      */
176     public static class DensityVerifier extends DigitVerifier { }
177 
178     /**
179      * Implementation of {@link VerifyListener} for the Screen Dimension qualifier.
180      */
181     public static class DimensionVerifier extends DigitVerifier { }
182 
183     /**
184      * Enum for the state of the configuration being created.
185      */
186     public enum ConfigurationState {
187         OK, INVALID_CONFIG, REGION_WITHOUT_LANGUAGE;
188     }
189 
190     /**
191      * A filter for {@link ResourceQualifier}.
192      * @see ConfigurationSelector#setQualifierFilter(IQualifierFilter)
193      */
194     public interface IQualifierFilter {
195         /**
196          * Returns true of the qualifier is accepted.
197          */
accept(ResourceQualifier qualifier)198         boolean accept(ResourceQualifier qualifier);
199     }
200 
201     /**
202      * Creates the selector.
203      *
204      * If the device mode is <code>true</code> then the configuration selector only
205      * allows to create configuration that are valid on a device (as opposed to resource
206      * configuration).
207      * For instance {@link Density#NODPI} is a valid qualifier for a resource configuration but
208      * this is not valid on a device.
209      * @param parent the composite parent.
210      * @param deviceMode the device mode.
211      */
ConfigurationSelector(Composite parent, boolean deviceMode)212     public ConfigurationSelector(Composite parent, boolean deviceMode) {
213         super(parent, SWT.NONE);
214         mDeviceMode  = deviceMode;
215 
216         mBaseConfiguration.createDefault();
217 
218         GridLayout gl = new GridLayout(4, false);
219         gl.marginWidth = gl.marginHeight = 0;
220         setLayout(gl);
221 
222         // first column is the first table
223         final Table fullTable = new Table(this, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER);
224         fullTable.setLayoutData(new GridData(GridData.FILL_BOTH));
225         fullTable.setHeaderVisible(true);
226         fullTable.setLinesVisible(true);
227 
228         // create the column
229         final TableColumn fullTableColumn = new TableColumn(fullTable, SWT.LEFT);
230         // set the header
231         fullTableColumn.setText("Available Qualifiers");
232 
233         fullTable.addControlListener(new ControlAdapter() {
234             @Override
235             public void controlResized(ControlEvent e) {
236                 Rectangle r = fullTable.getClientArea();
237                 fullTableColumn.setWidth(r.width);
238             }
239         });
240 
241         mFullTableViewer = new TableViewer(fullTable);
242         mFullTableViewer.setContentProvider(new QualifierContentProvider());
243         mFullTableViewer.setLabelProvider(new QualifierLabelProvider(
244                 false /* showQualifierValue */));
245         mFullTableViewer.setInput(mBaseConfiguration);
246         mFullTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
247             public void selectionChanged(SelectionChangedEvent event) {
248                 ISelection selection = event.getSelection();
249                 if (selection instanceof IStructuredSelection) {
250                     IStructuredSelection structSelection = (IStructuredSelection)selection;
251                     Object first = structSelection.getFirstElement();
252 
253                     if (first instanceof ResourceQualifier) {
254                         mAddButton.setEnabled(true);
255                         return;
256                     }
257                 }
258 
259                 mAddButton.setEnabled(false);
260             }
261         });
262 
263         // 2nd column is the left/right arrow button
264         Composite buttonComposite = new Composite(this, SWT.NONE);
265         gl = new GridLayout(1, false);
266         gl.marginWidth = gl.marginHeight = 0;
267         buttonComposite.setLayout(gl);
268         buttonComposite.setLayoutData(new GridData(GridData.FILL_VERTICAL));
269 
270         new Composite(buttonComposite, SWT.NONE);
271         mAddButton = new Button(buttonComposite, SWT.BORDER | SWT.PUSH);
272         mAddButton.setText("->");
273         mAddButton.setEnabled(false);
274         mAddButton.addSelectionListener(new SelectionAdapter() {
275             @Override
276             public void widgetSelected(SelectionEvent e) {
277                 IStructuredSelection selection =
278                     (IStructuredSelection)mFullTableViewer.getSelection();
279 
280                 Object first = selection.getFirstElement();
281                 if (first instanceof ResourceQualifier) {
282                     ResourceQualifier qualifier = (ResourceQualifier)first;
283 
284                     mBaseConfiguration.removeQualifier(qualifier);
285                     mSelectedConfiguration.addQualifier(qualifier);
286 
287                     mFullTableViewer.refresh();
288                     mSelectionTableViewer.refresh();
289                     mSelectionTableViewer.setSelection(new StructuredSelection(qualifier), true);
290 
291                     onChange(false /* keepSelection */);
292                 }
293             }
294         });
295 
296         mRemoveButton = new Button(buttonComposite, SWT.BORDER | SWT.PUSH);
297         mRemoveButton.setText("<-");
298         mRemoveButton.setEnabled(false);
299         mRemoveButton.addSelectionListener(new SelectionAdapter() {
300             @Override
301             public void widgetSelected(SelectionEvent e) {
302                 IStructuredSelection selection =
303                     (IStructuredSelection)mSelectionTableViewer.getSelection();
304 
305                 Object first = selection.getFirstElement();
306                 if (first instanceof ResourceQualifier) {
307                     ResourceQualifier qualifier = (ResourceQualifier)first;
308 
309                     mSelectedConfiguration.removeQualifier(qualifier);
310                     mBaseConfiguration.addQualifier(qualifier);
311 
312                     mFullTableViewer.refresh();
313                     mSelectionTableViewer.refresh();
314 
315                     onChange(false /* keepSelection */);
316                 }
317             }
318         });
319 
320         // 3rd column is the selected config table
321         final Table selectionTable = new Table(this, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER);
322         selectionTable.setLayoutData(new GridData(GridData.FILL_BOTH));
323         selectionTable.setHeaderVisible(true);
324         selectionTable.setLinesVisible(true);
325 
326         // create the column
327         final TableColumn selectionTableColumn = new TableColumn(selectionTable, SWT.LEFT);
328         // set the header
329         selectionTableColumn.setText("Chosen Qualifiers");
330 
331         selectionTable.addControlListener(new ControlAdapter() {
332             @Override
333             public void controlResized(ControlEvent e) {
334                 Rectangle r = selectionTable.getClientArea();
335                 selectionTableColumn.setWidth(r.width);
336             }
337         });
338         mSelectionTableViewer = new TableViewer(selectionTable);
339         mSelectionTableViewer.setContentProvider(new QualifierContentProvider());
340         mSelectionTableViewer.setLabelProvider(new QualifierLabelProvider(
341                 true /* showQualifierValue */));
342         mSelectionTableViewer.setInput(mSelectedConfiguration);
343         mSelectionTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
344             public void selectionChanged(SelectionChangedEvent event) {
345                 // ignore selection changes during resfreshes in some cases.
346                 if (mOnRefresh) {
347                     return;
348                 }
349 
350                 ISelection selection = event.getSelection();
351                 if (selection instanceof IStructuredSelection) {
352                     IStructuredSelection structSelection = (IStructuredSelection)selection;
353 
354                     if (structSelection.isEmpty() == false) {
355                         Object first = structSelection.getFirstElement();
356 
357                         if (first instanceof ResourceQualifier) {
358                             mRemoveButton.setEnabled(true);
359 
360                             QualifierEditBase composite = mUiMap.get(first.getClass());
361 
362                             if (composite != null) {
363                                 composite.setQualifier((ResourceQualifier)first);
364                             }
365 
366                             mStackLayout.topControl = composite;
367                             mQualifierEditParent.layout();
368 
369                             return;
370                         }
371                     } else {
372                         mStackLayout.topControl = null;
373                         mQualifierEditParent.layout();
374                     }
375                 }
376 
377                 mRemoveButton.setEnabled(false);
378             }
379         });
380 
381         // 4th column is the detail of the selected qualifier
382         mQualifierEditParent = new Composite(this, SWT.NONE);
383         mQualifierEditParent.setLayout(mStackLayout = new StackLayout());
384         mQualifierEditParent.setLayoutData(new GridData(GridData.FILL_VERTICAL));
385 
386         // create the UI for all the qualifiers, and associate them to the ResourceQualifer class.
387         mUiMap.put(CountryCodeQualifier.class, new MCCEdit(mQualifierEditParent));
388         mUiMap.put(NetworkCodeQualifier.class, new MNCEdit(mQualifierEditParent));
389         mUiMap.put(LanguageQualifier.class, new LanguageEdit(mQualifierEditParent));
390         mUiMap.put(RegionQualifier.class, new RegionEdit(mQualifierEditParent));
391         mUiMap.put(ScreenSizeQualifier.class, new ScreenSizeEdit(mQualifierEditParent));
392         mUiMap.put(ScreenRatioQualifier.class, new ScreenRatioEdit(mQualifierEditParent));
393         mUiMap.put(ScreenOrientationQualifier.class, new OrientationEdit(mQualifierEditParent));
394         mUiMap.put(PixelDensityQualifier.class, new PixelDensityEdit(mQualifierEditParent));
395         mUiMap.put(TouchScreenQualifier.class, new TouchEdit(mQualifierEditParent));
396         mUiMap.put(KeyboardStateQualifier.class, new KeyboardEdit(mQualifierEditParent));
397         mUiMap.put(TextInputMethodQualifier.class, new TextInputEdit(mQualifierEditParent));
398         mUiMap.put(NavigationMethodQualifier.class, new NavigationEdit(mQualifierEditParent));
399         mUiMap.put(ScreenDimensionQualifier.class, new ScreenDimensionEdit(mQualifierEditParent));
400         mUiMap.put(VersionQualifier.class, new VersionEdit(mQualifierEditParent));
401     }
402 
403     /**
404      * Sets a {@link IQualifierFilter}. If non null, this will restrict the qualifiers that
405      * can be chosen.
406      * @param filter the filter to set.
407      */
setQualifierFilter(IQualifierFilter filter)408     public void setQualifierFilter(IQualifierFilter filter) {
409         mQualifierFilter = filter;
410     }
411 
412     /**
413      * Sets a listener to be notified when the configuration changes.
414      * @param listener A {@link Runnable} whose <code>run()</code> method is called when the
415      * configuration is changed. The method is called from the UI thread.
416      */
setOnChangeListener(Runnable listener)417     public void setOnChangeListener(Runnable listener) {
418         mOnChangeListener = listener;
419     }
420 
421     /**
422      * Initialize the UI with a given {@link FolderConfiguration}. This must
423      * be called from the UI thread.
424      * @param config The configuration.
425      */
setConfiguration(FolderConfiguration config)426     public void setConfiguration(FolderConfiguration config) {
427         mSelectedConfiguration.set(config);
428         mSelectionTableViewer.refresh();
429 
430         // create the base config, which is the default config minus the qualifiers
431         // in SelectedConfiguration
432         mBaseConfiguration.substract(mSelectedConfiguration);
433         mFullTableViewer.refresh();
434     }
435 
436     /**
437      * Initialize the UI with the configuration represented by a resource folder name.
438      * This must be called from the UI thread.
439      *
440      * @param folderSegments the segments of the folder name,
441      *                       split using {@link FolderConfiguration#QUALIFIER_SEP}.
442      * @return true if success, or false if the folder name is not a valid name.
443      */
setConfiguration(String[] folderSegments)444     public boolean setConfiguration(String[] folderSegments) {
445         FolderConfiguration config = ResourceManager.getInstance().getConfig(folderSegments);
446 
447         if (config == null) {
448             return false;
449         }
450 
451         setConfiguration(config);
452 
453         return true;
454     }
455 
456     /**
457      * Initialize the UI with the configuration represented by a resource folder name.
458      * This must be called from the UI thread.
459      * @param folderName the name of the folder.
460      * @return true if success, or false if the folder name is not a valid name.
461      */
setConfiguration(String folderName)462     public boolean setConfiguration(String folderName) {
463         // split the name of the folder in segments.
464         String[] folderSegments = folderName.split(FolderConfiguration.QUALIFIER_SEP);
465 
466         return setConfiguration(folderSegments);
467     }
468 
469     /**
470      * Gets the configuration as setup by the widget.
471      * @param config the {@link FolderConfiguration} object to be filled with the information
472      * from the UI.
473      */
getConfiguration(FolderConfiguration config)474     public void getConfiguration(FolderConfiguration config) {
475         config.set(mSelectedConfiguration);
476     }
477 
478     /**
479      * Returns the state of the configuration being edited/created.
480      */
getState()481     public ConfigurationState getState() {
482         if (mSelectedConfiguration.getInvalidQualifier() != null) {
483             return ConfigurationState.INVALID_CONFIG;
484         }
485 
486         if (mSelectedConfiguration.checkRegion() == false) {
487             return ConfigurationState.REGION_WITHOUT_LANGUAGE;
488         }
489 
490         return ConfigurationState.OK;
491     }
492 
493     /**
494      * Returns the first invalid qualifier of the configuration being edited/created,
495      * or <code>null<code> if they are all valid (or if none exists).
496      * <p/>If {@link #getState()} return {@link ConfigurationState#INVALID_CONFIG} then this will
497      * not return <code>null</code>.
498      */
getInvalidQualifier()499     public ResourceQualifier getInvalidQualifier() {
500         return mSelectedConfiguration.getInvalidQualifier();
501     }
502 
503     /**
504      * Handle changes in the configuration.
505      * @param keepSelection if <code>true</code> attemps to avoid triggering selection change in
506      * {@link #mSelectedConfiguration}.
507      */
onChange(boolean keepSelection)508     private void onChange(boolean keepSelection) {
509         ISelection selection = null;
510         if (keepSelection) {
511             mOnRefresh = true;
512             selection = mSelectionTableViewer.getSelection();
513         }
514 
515         mSelectionTableViewer.refresh(true);
516 
517         if (keepSelection) {
518             mSelectionTableViewer.setSelection(selection);
519             mOnRefresh = false;
520         }
521 
522         if (mOnChangeListener != null) {
523             mOnChangeListener.run();
524         }
525     }
526 
527     /**
528      * Content provider around a {@link FolderConfiguration}.
529      */
530     private class QualifierContentProvider implements IStructuredContentProvider {
531 
532         private FolderConfiguration mInput;
533 
QualifierContentProvider()534         public QualifierContentProvider() {
535         }
536 
dispose()537         public void dispose() {
538             // pass
539         }
540 
getElements(Object inputElement)541         public Object[] getElements(Object inputElement) {
542             // default easy case
543             if (mQualifierFilter == null) {
544                 return mInput.getQualifiers();
545             }
546 
547             // in this case we have to compute the list
548             ArrayList<ResourceQualifier> list = new ArrayList<ResourceQualifier>();
549             for (ResourceQualifier qual : mInput.getQualifiers()) {
550                 if (mQualifierFilter.accept(qual)) {
551                     list.add(qual);
552                 }
553             }
554 
555             return list.toArray();
556         }
557 
inputChanged(Viewer viewer, Object oldInput, Object newInput)558         public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
559             mInput = null;
560             if (newInput instanceof FolderConfiguration) {
561                 mInput = (FolderConfiguration)newInput;
562             }
563         }
564     }
565 
566     /**
567      * Label provider for {@link ResourceQualifier} objects.
568      */
569     private static class QualifierLabelProvider implements ITableLabelProvider {
570 
571         private final boolean mShowQualifierValue;
572 
QualifierLabelProvider(boolean showQualifierValue)573         public QualifierLabelProvider(boolean showQualifierValue) {
574             mShowQualifierValue = showQualifierValue;
575         }
576 
getColumnText(Object element, int columnIndex)577         public String getColumnText(Object element, int columnIndex) {
578             // only one column, so we can ignore columnIndex
579             if (element instanceof ResourceQualifier) {
580                 if (mShowQualifierValue) {
581                     String value = ((ResourceQualifier)element).getStringValue();
582                     if (value.length() == 0) {
583                         return String.format("%1$s (?)",
584                                 ((ResourceQualifier)element).getShortName());
585                     } else {
586                         return value;
587                     }
588 
589                 } else {
590                     return ((ResourceQualifier)element).getShortName();
591                 }
592             }
593 
594             return null;
595         }
596 
getColumnImage(Object element, int columnIndex)597         public Image getColumnImage(Object element, int columnIndex) {
598             // only one column, so we can ignore columnIndex
599             if (element instanceof ResourceQualifier) {
600                 return ((ResourceQualifier)element).getIcon();
601             }
602 
603             return null;
604         }
605 
addListener(ILabelProviderListener listener)606         public void addListener(ILabelProviderListener listener) {
607             // pass
608         }
609 
dispose()610         public void dispose() {
611             // pass
612         }
613 
isLabelProperty(Object element, String property)614         public boolean isLabelProperty(Object element, String property) {
615             // pass
616             return false;
617         }
618 
removeListener(ILabelProviderListener listener)619         public void removeListener(ILabelProviderListener listener) {
620             // pass
621         }
622     }
623 
624     /**
625      * Base class for Edit widget for {@link ResourceQualifier}.
626      */
627     private abstract static class QualifierEditBase extends Composite {
628 
QualifierEditBase(Composite parent, String title)629         public QualifierEditBase(Composite parent, String title) {
630             super(parent, SWT.NONE);
631             setLayout(new GridLayout(1, false));
632 
633             new Label(this, SWT.NONE).setText(title);
634         }
635 
setQualifier(ResourceQualifier qualifier)636         public abstract void setQualifier(ResourceQualifier qualifier);
637     }
638 
639     /**
640      * Edit widget for {@link CountryCodeQualifier}.
641      */
642     private class MCCEdit extends QualifierEditBase {
643 
644         private Text mText;
645 
MCCEdit(Composite parent)646         public MCCEdit(Composite parent) {
647             super(parent, CountryCodeQualifier.NAME);
648 
649             mText = new Text(this, SWT.BORDER);
650             mText.addVerifyListener(new MobileCodeVerifier());
651             mText.addModifyListener(new ModifyListener() {
652                 public void modifyText(ModifyEvent e) {
653                     onTextChange();
654                 }
655             });
656 
657             mText.addFocusListener(new FocusAdapter() {
658                 @Override
659                 public void focusLost(FocusEvent e) {
660                     onTextChange();
661                 }
662             });
663 
664             new Label(this, SWT.NONE).setText("(3 digit code)");
665         }
666 
onTextChange()667         private void onTextChange() {
668             String value = mText.getText();
669 
670             if (value.length() == 0) {
671                 // empty string, means a qualifier with no value.
672                 // Since the qualifier classes are immutable, and we don't want to
673                 // remove the qualifier from the configuration, we create a new default one.
674                 mSelectedConfiguration.setCountryCodeQualifier(new CountryCodeQualifier());
675             } else {
676                 try {
677                     CountryCodeQualifier qualifier = CountryCodeQualifier.getQualifier(
678                             CountryCodeQualifier.getFolderSegment(Integer.parseInt(value)));
679                     if (qualifier != null) {
680                         mSelectedConfiguration.setCountryCodeQualifier(qualifier);
681                     } else {
682                         // Failure! Looks like the value is wrong
683                         // (for instance not exactly 3 digits).
684                         mSelectedConfiguration.setCountryCodeQualifier(new CountryCodeQualifier());
685                     }
686                 } catch (NumberFormatException nfe) {
687                     // Looks like the code is not a number. This should not happen since the text
688                     // field has a VerifyListener that prevents it.
689                     mSelectedConfiguration.setCountryCodeQualifier(new CountryCodeQualifier());
690                 }
691             }
692 
693             // notify of change
694             onChange(true /* keepSelection */);
695         }
696 
697         @Override
setQualifier(ResourceQualifier qualifier)698         public void setQualifier(ResourceQualifier qualifier) {
699             CountryCodeQualifier q = (CountryCodeQualifier)qualifier;
700 
701             mText.setText(Integer.toString(q.getCode()));
702         }
703     }
704 
705     /**
706      * Edit widget for {@link NetworkCodeQualifier}.
707      */
708     private class MNCEdit extends QualifierEditBase {
709         private Text mText;
710 
MNCEdit(Composite parent)711         public MNCEdit(Composite parent) {
712             super(parent, NetworkCodeQualifier.NAME);
713 
714             mText = new Text(this, SWT.BORDER);
715             mText.addVerifyListener(new MobileCodeVerifier());
716             mText.addModifyListener(new ModifyListener() {
717                 public void modifyText(ModifyEvent e) {
718                     onTextChange();
719                 }
720             });
721             mText.addFocusListener(new FocusAdapter() {
722                 @Override
723                 public void focusLost(FocusEvent e) {
724                     onTextChange();
725                 }
726             });
727 
728             new Label(this, SWT.NONE).setText("(1-3 digit code)");
729         }
730 
onTextChange()731         private void onTextChange() {
732             String value = mText.getText();
733 
734             if (value.length() == 0) {
735                 // empty string, means a qualifier with no value.
736                 // Since the qualifier classes are immutable, and we don't want to
737                 // remove the qualifier from the configuration, we create a new default one.
738                 mSelectedConfiguration.setNetworkCodeQualifier(new NetworkCodeQualifier());
739             } else {
740                 try {
741                     NetworkCodeQualifier qualifier = NetworkCodeQualifier.getQualifier(
742                             NetworkCodeQualifier.getFolderSegment(Integer.parseInt(value)));
743                     if (qualifier != null) {
744                         mSelectedConfiguration.setNetworkCodeQualifier(qualifier);
745                     } else {
746                         // Failure! Looks like the value is wrong
747                         // (for instance not exactly 3 digits).
748                         mSelectedConfiguration.setNetworkCodeQualifier(new NetworkCodeQualifier());
749                     }
750                 } catch (NumberFormatException nfe) {
751                     // Looks like the code is not a number. This should not happen since the text
752                     // field has a VerifyListener that prevents it.
753                     mSelectedConfiguration.setNetworkCodeQualifier(new NetworkCodeQualifier());
754                 }
755             }
756 
757             // notify of change
758             onChange(true /* keepSelection */);
759         }
760 
761         @Override
setQualifier(ResourceQualifier qualifier)762         public void setQualifier(ResourceQualifier qualifier) {
763             NetworkCodeQualifier q = (NetworkCodeQualifier)qualifier;
764 
765             mText.setText(Integer.toString(q.getCode()));
766         }
767     }
768 
769     /**
770      * Edit widget for {@link LanguageQualifier}.
771      */
772     private class LanguageEdit extends QualifierEditBase {
773         private Combo mLanguage;
774 
LanguageEdit(Composite parent)775         public LanguageEdit(Composite parent) {
776             super(parent, LanguageQualifier.NAME);
777 
778             mLanguage = new Combo(this, SWT.DROP_DOWN);
779             mLanguage.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
780             mLanguage.addVerifyListener(new LanguageRegionVerifier());
781             mLanguage.addSelectionListener(new SelectionListener() {
782                 public void widgetDefaultSelected(SelectionEvent e) {
783                     onLanguageChange();
784                 }
785                 public void widgetSelected(SelectionEvent e) {
786                     onLanguageChange();
787                 }
788             });
789             mLanguage.addModifyListener(new ModifyListener() {
790                 public void modifyText(ModifyEvent e) {
791                     onLanguageChange();
792                 }
793             });
794 
795             new Label(this, SWT.NONE).setText("(2 letter code)");
796         }
797 
onLanguageChange()798         private void onLanguageChange() {
799             // update the current config
800             String value = mLanguage.getText();
801 
802             if (value.length() == 0) {
803                 // empty string, means no qualifier.
804                 // Since the qualifier classes are immutable, and we don't want to
805                 // remove the qualifier from the configuration, we create a new default one.
806                 mSelectedConfiguration.setLanguageQualifier(new LanguageQualifier());
807             } else {
808                 LanguageQualifier qualifier = null;
809                 String segment = LanguageQualifier.getFolderSegment(value);
810                 if (segment != null) {
811                     qualifier = LanguageQualifier.getQualifier(segment);
812                 }
813 
814                 if (qualifier != null) {
815                     mSelectedConfiguration.setLanguageQualifier(qualifier);
816                 } else {
817                     // Failure! Looks like the value is wrong (for instance a one letter string).
818                     mSelectedConfiguration.setLanguageQualifier(new LanguageQualifier());
819                 }
820             }
821 
822             // notify of change
823             onChange(true /* keepSelection */);
824         }
825 
826         @Override
setQualifier(ResourceQualifier qualifier)827         public void setQualifier(ResourceQualifier qualifier) {
828             LanguageQualifier q = (LanguageQualifier)qualifier;
829 
830             String value = q.getValue();
831             if (value != null) {
832                 mLanguage.setText(value);
833             }
834         }
835     }
836 
837     /**
838      * Edit widget for {@link RegionQualifier}.
839      */
840     private class RegionEdit extends QualifierEditBase {
841         private Combo mRegion;
842 
RegionEdit(Composite parent)843         public RegionEdit(Composite parent) {
844             super(parent, RegionQualifier.NAME);
845 
846             mRegion = new Combo(this, SWT.DROP_DOWN);
847             mRegion.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
848             mRegion.addVerifyListener(new LanguageRegionVerifier());
849             mRegion.addSelectionListener(new SelectionListener() {
850                 public void widgetDefaultSelected(SelectionEvent e) {
851                     onRegionChange();
852                 }
853                 public void widgetSelected(SelectionEvent e) {
854                     onRegionChange();
855                 }
856             });
857             mRegion.addModifyListener(new ModifyListener() {
858                 public void modifyText(ModifyEvent e) {
859                     onRegionChange();
860                 }
861             });
862 
863             new Label(this, SWT.NONE).setText("(2 letter code)");
864         }
865 
onRegionChange()866         private void onRegionChange() {
867             // update the current config
868             String value = mRegion.getText();
869 
870             if (value.length() == 0) {
871                 // empty string, means no qualifier.
872                 // Since the qualifier classes are immutable, and we don't want to
873                 // remove the qualifier from the configuration, we create a new default one.
874                 mSelectedConfiguration.setRegionQualifier(new RegionQualifier());
875             } else {
876                 RegionQualifier qualifier = null;
877                 String segment = RegionQualifier.getFolderSegment(value);
878                 if (segment != null) {
879                     qualifier = RegionQualifier.getQualifier(segment);
880                 }
881 
882                 if (qualifier != null) {
883                     mSelectedConfiguration.setRegionQualifier(qualifier);
884                 } else {
885                     // Failure! Looks like the value is wrong (for instance a one letter string).
886                     mSelectedConfiguration.setRegionQualifier(new RegionQualifier());
887                 }
888             }
889 
890             // notify of change
891             onChange(true /* keepSelection */);
892         }
893 
894         @Override
setQualifier(ResourceQualifier qualifier)895         public void setQualifier(ResourceQualifier qualifier) {
896             RegionQualifier q = (RegionQualifier)qualifier;
897 
898             String value = q.getValue();
899             if (value != null) {
900                 mRegion.setText(q.getValue());
901             }
902         }
903     }
904 
905     /**
906      * Edit widget for {@link ScreenSizeQualifier}.
907      */
908     private class ScreenSizeEdit extends QualifierEditBase {
909 
910         private Combo mSize;
911 
ScreenSizeEdit(Composite parent)912         public ScreenSizeEdit(Composite parent) {
913             super(parent, ScreenSizeQualifier.NAME);
914 
915             mSize = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
916             ScreenSize[] ssValues = ScreenSize.values();
917             for (ScreenSize value : ssValues) {
918                 mSize.add(value.getDisplayValue());
919             }
920 
921             mSize.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
922             mSize.addSelectionListener(new SelectionListener() {
923                 public void widgetDefaultSelected(SelectionEvent e) {
924                     onScreenSizeChange();
925                 }
926                 public void widgetSelected(SelectionEvent e) {
927                     onScreenSizeChange();
928                 }
929             });
930         }
931 
onScreenSizeChange()932         protected void onScreenSizeChange() {
933             // update the current config
934             int index = mSize.getSelectionIndex();
935 
936             if (index != -1) {
937                 mSelectedConfiguration.setScreenSizeQualifier(new ScreenSizeQualifier(
938                     ScreenSize.getByIndex(index)));
939             } else {
940                 // empty selection, means no qualifier.
941                 // Since the qualifier classes are immutable, and we don't want to
942                 // remove the qualifier from the configuration, we create a new default one.
943                 mSelectedConfiguration.setScreenSizeQualifier(
944                         new ScreenSizeQualifier());
945             }
946 
947             // notify of change
948             onChange(true /* keepSelection */);
949         }
950 
951         @Override
setQualifier(ResourceQualifier qualifier)952         public void setQualifier(ResourceQualifier qualifier) {
953             ScreenSizeQualifier q = (ScreenSizeQualifier)qualifier;
954 
955             ScreenSize value = q.getValue();
956             if (value == null) {
957                 mSize.clearSelection();
958             } else {
959                 mSize.select(ScreenSize.getIndex(value));
960             }
961         }
962     }
963 
964     /**
965      * Edit widget for {@link ScreenRatioQualifier}.
966      */
967     private class ScreenRatioEdit extends QualifierEditBase {
968 
969         private Combo mSize;
970 
ScreenRatioEdit(Composite parent)971         public ScreenRatioEdit(Composite parent) {
972             super(parent, ScreenRatioQualifier.NAME);
973 
974             mSize = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
975             ScreenRatio[] srValues = ScreenRatio.values();
976             for (ScreenRatio value : srValues) {
977                 mSize.add(value.getDisplayValue());
978             }
979 
980             mSize.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
981             mSize.addSelectionListener(new SelectionListener() {
982                 public void widgetDefaultSelected(SelectionEvent e) {
983                     onScreenRatioChange();
984                 }
985                 public void widgetSelected(SelectionEvent e) {
986                     onScreenRatioChange();
987                 }
988             });
989         }
990 
onScreenRatioChange()991         protected void onScreenRatioChange() {
992             // update the current config
993             int index = mSize.getSelectionIndex();
994 
995             if (index != -1) {
996                 mSelectedConfiguration.setScreenRatioQualifier(new ScreenRatioQualifier(
997                         ScreenRatio.getByIndex(index)));
998             } else {
999                 // empty selection, means no qualifier.
1000                 // Since the qualifier classes are immutable, and we don't want to
1001                 // remove the qualifier from the configuration, we create a new default one.
1002                 mSelectedConfiguration.setScreenRatioQualifier(
1003                         new ScreenRatioQualifier());
1004             }
1005 
1006             // notify of change
1007             onChange(true /* keepSelection */);
1008         }
1009 
1010         @Override
setQualifier(ResourceQualifier qualifier)1011         public void setQualifier(ResourceQualifier qualifier) {
1012             ScreenRatioQualifier q = (ScreenRatioQualifier)qualifier;
1013 
1014             ScreenRatio value = q.getValue();
1015             if (value == null) {
1016                 mSize.clearSelection();
1017             } else {
1018                 mSize.select(ScreenRatio.getIndex(value));
1019             }
1020         }
1021     }
1022 
1023     /**
1024      * Edit widget for {@link ScreenOrientationQualifier}.
1025      */
1026     private class OrientationEdit extends QualifierEditBase {
1027 
1028         private Combo mOrientation;
1029 
OrientationEdit(Composite parent)1030         public OrientationEdit(Composite parent) {
1031             super(parent, ScreenOrientationQualifier.NAME);
1032 
1033             mOrientation = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
1034             ScreenOrientation[] soValues = ScreenOrientation.values();
1035             for (ScreenOrientation value : soValues) {
1036                 mOrientation.add(value.getDisplayValue());
1037             }
1038 
1039             mOrientation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1040             mOrientation.addSelectionListener(new SelectionListener() {
1041                 public void widgetDefaultSelected(SelectionEvent e) {
1042                     onOrientationChange();
1043                 }
1044                 public void widgetSelected(SelectionEvent e) {
1045                     onOrientationChange();
1046                 }
1047             });
1048         }
1049 
onOrientationChange()1050         protected void onOrientationChange() {
1051             // update the current config
1052             int index = mOrientation.getSelectionIndex();
1053 
1054             if (index != -1) {
1055                 mSelectedConfiguration.setScreenOrientationQualifier(new ScreenOrientationQualifier(
1056                     ScreenOrientation.getByIndex(index)));
1057             } else {
1058                 // empty selection, means no qualifier.
1059                 // Since the qualifier classes are immutable, and we don't want to
1060                 // remove the qualifier from the configuration, we create a new default one.
1061                 mSelectedConfiguration.setScreenOrientationQualifier(
1062                         new ScreenOrientationQualifier());
1063             }
1064 
1065             // notify of change
1066             onChange(true /* keepSelection */);
1067         }
1068 
1069         @Override
setQualifier(ResourceQualifier qualifier)1070         public void setQualifier(ResourceQualifier qualifier) {
1071             ScreenOrientationQualifier q = (ScreenOrientationQualifier)qualifier;
1072 
1073             ScreenOrientation value = q.getValue();
1074             if (value == null) {
1075                 mOrientation.clearSelection();
1076             } else {
1077                 mOrientation.select(ScreenOrientation.getIndex(value));
1078             }
1079         }
1080     }
1081 
1082     /**
1083      * Edit widget for {@link PixelDensityQualifier}.
1084      */
1085     private class PixelDensityEdit extends QualifierEditBase {
1086         private Combo mDensity;
1087 
PixelDensityEdit(Composite parent)1088         public PixelDensityEdit(Composite parent) {
1089             super(parent, PixelDensityQualifier.NAME);
1090 
1091             mDensity = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
1092             Density[] soValues = Density.values();
1093             for (Density value : soValues) {
1094                 if (mDeviceMode == false || value != Density.NODPI) {
1095                     mDensity.add(value.getDisplayValue());
1096                 }
1097             }
1098 
1099             mDensity.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1100             mDensity.addSelectionListener(new SelectionListener() {
1101                 public void widgetDefaultSelected(SelectionEvent e) {
1102                     onDensityChange();
1103                 }
1104                 public void widgetSelected(SelectionEvent e) {
1105                     onDensityChange();
1106                 }
1107             });
1108         }
1109 
onDensityChange()1110         private void onDensityChange() {
1111             // update the current config
1112             int index = mDensity.getSelectionIndex();
1113 
1114             if (index != -1) {
1115                 mSelectedConfiguration.setPixelDensityQualifier(new PixelDensityQualifier(
1116                     Density.getByIndex(index)));
1117             } else {
1118                 // empty selection, means 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.setPixelDensityQualifier(
1122                         new PixelDensityQualifier());
1123             }
1124 
1125             // notify of change
1126             onChange(true /* keepSelection */);
1127         }
1128 
1129         @Override
setQualifier(ResourceQualifier qualifier)1130         public void setQualifier(ResourceQualifier qualifier) {
1131             PixelDensityQualifier q = (PixelDensityQualifier)qualifier;
1132 
1133             Density value = q.getValue();
1134             if (value == null) {
1135                 mDensity.clearSelection();
1136             } else {
1137                 mDensity.select(Density.getIndex(value));
1138             }
1139         }
1140     }
1141 
1142     /**
1143      * Edit widget for {@link TouchScreenQualifier}.
1144      */
1145     private class TouchEdit extends QualifierEditBase {
1146 
1147         private Combo mTouchScreen;
1148 
TouchEdit(Composite parent)1149         public TouchEdit(Composite parent) {
1150             super(parent, TouchScreenQualifier.NAME);
1151 
1152             mTouchScreen = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
1153             TouchScreenType[] tstValues = TouchScreenType.values();
1154             for (TouchScreenType value : tstValues) {
1155                 mTouchScreen.add(value.getDisplayValue());
1156             }
1157 
1158             mTouchScreen.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1159             mTouchScreen.addSelectionListener(new SelectionListener() {
1160                 public void widgetDefaultSelected(SelectionEvent e) {
1161                     onTouchChange();
1162                 }
1163                 public void widgetSelected(SelectionEvent e) {
1164                     onTouchChange();
1165                 }
1166             });
1167         }
1168 
onTouchChange()1169         protected void onTouchChange() {
1170             // update the current config
1171             int index = mTouchScreen.getSelectionIndex();
1172 
1173             if (index != -1) {
1174                 mSelectedConfiguration.setTouchTypeQualifier(new TouchScreenQualifier(
1175                         TouchScreenType.getByIndex(index)));
1176             } else {
1177                 // empty selection, means no qualifier.
1178                 // Since the qualifier classes are immutable, and we don't want to
1179                 // remove the qualifier from the configuration, we create a new default one.
1180                 mSelectedConfiguration.setTouchTypeQualifier(new TouchScreenQualifier());
1181             }
1182 
1183             // notify of change
1184             onChange(true /* keepSelection */);
1185         }
1186 
1187         @Override
setQualifier(ResourceQualifier qualifier)1188         public void setQualifier(ResourceQualifier qualifier) {
1189             TouchScreenQualifier q = (TouchScreenQualifier)qualifier;
1190 
1191             TouchScreenType value = q.getValue();
1192             if (value == null) {
1193                 mTouchScreen.clearSelection();
1194             } else {
1195                 mTouchScreen.select(TouchScreenType.getIndex(value));
1196             }
1197         }
1198     }
1199 
1200     /**
1201      * Edit widget for {@link KeyboardStateQualifier}.
1202      */
1203     private class KeyboardEdit extends QualifierEditBase {
1204 
1205         private Combo mKeyboard;
1206 
KeyboardEdit(Composite parent)1207         public KeyboardEdit(Composite parent) {
1208             super(parent, KeyboardStateQualifier.NAME);
1209 
1210             mKeyboard = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
1211             KeyboardState[] ksValues = KeyboardState.values();
1212             for (KeyboardState value : ksValues) {
1213                 mKeyboard.add(value.getDisplayValue());
1214             }
1215 
1216             mKeyboard.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1217             mKeyboard.addSelectionListener(new SelectionListener() {
1218                 public void widgetDefaultSelected(SelectionEvent e) {
1219                     onKeyboardChange();
1220                 }
1221                 public void widgetSelected(SelectionEvent e) {
1222                     onKeyboardChange();
1223                 }
1224             });
1225         }
1226 
onKeyboardChange()1227         protected void onKeyboardChange() {
1228             // update the current config
1229             int index = mKeyboard.getSelectionIndex();
1230 
1231             if (index != -1) {
1232                 mSelectedConfiguration.setKeyboardStateQualifier(new KeyboardStateQualifier(
1233                         KeyboardState.getByIndex(index)));
1234             } else {
1235                 // empty selection, means no qualifier.
1236                 // Since the qualifier classes are immutable, and we don't want to
1237                 // remove the qualifier from the configuration, we create a new default one.
1238                 mSelectedConfiguration.setKeyboardStateQualifier(
1239                         new KeyboardStateQualifier());
1240             }
1241 
1242             // notify of change
1243             onChange(true /* keepSelection */);
1244         }
1245 
1246         @Override
setQualifier(ResourceQualifier qualifier)1247         public void setQualifier(ResourceQualifier qualifier) {
1248             KeyboardStateQualifier q = (KeyboardStateQualifier)qualifier;
1249 
1250             KeyboardState value = q.getValue();
1251             if (value == null) {
1252                 mKeyboard.clearSelection();
1253             } else {
1254                 mKeyboard.select(KeyboardState.getIndex(value));
1255             }
1256         }
1257     }
1258 
1259     /**
1260      * Edit widget for {@link TextInputMethodQualifier}.
1261      */
1262     private class TextInputEdit extends QualifierEditBase {
1263 
1264         private Combo mTextInput;
1265 
TextInputEdit(Composite parent)1266         public TextInputEdit(Composite parent) {
1267             super(parent, TextInputMethodQualifier.NAME);
1268 
1269             mTextInput = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
1270             TextInputMethod[] timValues = TextInputMethod.values();
1271             for (TextInputMethod value : timValues) {
1272                 mTextInput.add(value.getDisplayValue());
1273             }
1274 
1275             mTextInput.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1276             mTextInput.addSelectionListener(new SelectionListener() {
1277                 public void widgetDefaultSelected(SelectionEvent e) {
1278                     onTextInputChange();
1279                 }
1280                 public void widgetSelected(SelectionEvent e) {
1281                     onTextInputChange();
1282                 }
1283             });
1284         }
1285 
onTextInputChange()1286         protected void onTextInputChange() {
1287             // update the current config
1288             int index = mTextInput.getSelectionIndex();
1289 
1290             if (index != -1) {
1291                 mSelectedConfiguration.setTextInputMethodQualifier(new TextInputMethodQualifier(
1292                         TextInputMethod.getByIndex(index)));
1293             } else {
1294                 // empty selection, means no qualifier.
1295                 // Since the qualifier classes are immutable, and we don't want to
1296                 // remove the qualifier from the configuration, we create a new default one.
1297                 mSelectedConfiguration.setTextInputMethodQualifier(
1298                         new TextInputMethodQualifier());
1299             }
1300 
1301             // notify of change
1302             onChange(true /* keepSelection */);
1303         }
1304 
1305         @Override
setQualifier(ResourceQualifier qualifier)1306         public void setQualifier(ResourceQualifier qualifier) {
1307             TextInputMethodQualifier q = (TextInputMethodQualifier)qualifier;
1308 
1309             TextInputMethod value = q.getValue();
1310             if (value == null) {
1311                 mTextInput.clearSelection();
1312             } else {
1313                 mTextInput.select(TextInputMethod.getIndex(value));
1314             }
1315         }
1316     }
1317 
1318     /**
1319      * Edit widget for {@link NavigationMethodQualifier}.
1320      */
1321     private class NavigationEdit extends QualifierEditBase {
1322 
1323         private Combo mNavigation;
1324 
NavigationEdit(Composite parent)1325         public NavigationEdit(Composite parent) {
1326             super(parent, NavigationMethodQualifier.NAME);
1327 
1328             mNavigation = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
1329             NavigationMethod[] nmValues = NavigationMethod.values();
1330             for (NavigationMethod value : nmValues) {
1331                 mNavigation.add(value.getDisplayValue());
1332             }
1333 
1334             mNavigation.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
1335             mNavigation.addSelectionListener(new SelectionListener() {
1336                 public void widgetDefaultSelected(SelectionEvent e) {
1337                     onNavigationChange();
1338                 }
1339                 public void widgetSelected(SelectionEvent e) {
1340                     onNavigationChange();
1341                 }
1342             });
1343         }
1344 
onNavigationChange()1345         protected void onNavigationChange() {
1346             // update the current config
1347             int index = mNavigation.getSelectionIndex();
1348 
1349             if (index != -1) {
1350                 mSelectedConfiguration.setNavigationMethodQualifier(new NavigationMethodQualifier(
1351                         NavigationMethod.getByIndex(index)));
1352             } else {
1353                 // empty selection, means no qualifier.
1354                 // Since the qualifier classes are immutable, and we don't want to
1355                 // remove the qualifier from the configuration, we create a new default one.
1356                 mSelectedConfiguration.setNavigationMethodQualifier(
1357                         new NavigationMethodQualifier());
1358             }
1359 
1360             // notify of change
1361             onChange(true /* keepSelection */);
1362         }
1363 
1364         @Override
setQualifier(ResourceQualifier qualifier)1365         public void setQualifier(ResourceQualifier qualifier) {
1366             NavigationMethodQualifier q = (NavigationMethodQualifier)qualifier;
1367 
1368             NavigationMethod value = q.getValue();
1369             if (value == null) {
1370                 mNavigation.clearSelection();
1371             } else {
1372                 mNavigation.select(NavigationMethod.getIndex(value));
1373             }
1374         }
1375     }
1376 
1377     /**
1378      * Edit widget for {@link ScreenDimensionQualifier}.
1379      */
1380     private class ScreenDimensionEdit extends QualifierEditBase {
1381 
1382         private Text mSize1;
1383         private Text mSize2;
1384 
ScreenDimensionEdit(Composite parent)1385         public ScreenDimensionEdit(Composite parent) {
1386             super(parent, ScreenDimensionQualifier.NAME);
1387 
1388             ModifyListener modifyListener = new ModifyListener() {
1389                 public void modifyText(ModifyEvent e) {
1390                     onSizeChange();
1391                 }
1392             };
1393 
1394             FocusAdapter focusListener = new FocusAdapter() {
1395                 @Override
1396                 public void focusLost(FocusEvent e) {
1397                     onSizeChange();
1398                 }
1399             };
1400 
1401             mSize1 = new Text(this, SWT.BORDER);
1402             mSize1.addVerifyListener(new DimensionVerifier());
1403             mSize1.addModifyListener(modifyListener);
1404             mSize1.addFocusListener(focusListener);
1405 
1406             mSize2 = new Text(this, SWT.BORDER);
1407             mSize2.addVerifyListener(new DimensionVerifier());
1408             mSize2.addModifyListener(modifyListener);
1409             mSize2.addFocusListener(focusListener);
1410         }
1411 
onSizeChange()1412         private void onSizeChange() {
1413             // update the current config
1414             String size1 = mSize1.getText();
1415             String size2 = mSize2.getText();
1416 
1417             if (size1.length() == 0 || size2.length() == 0) {
1418                 // if one of the strings is empty, reset to no qualifier.
1419                 // Since the qualifier classes are immutable, and we don't want to
1420                 // remove the qualifier from the configuration, we create a new default one.
1421                 mSelectedConfiguration.setScreenDimensionQualifier(new ScreenDimensionQualifier());
1422             } else {
1423                 ScreenDimensionQualifier qualifier = ScreenDimensionQualifier.getQualifier(size1,
1424                         size2);
1425 
1426                 if (qualifier != null) {
1427                     mSelectedConfiguration.setScreenDimensionQualifier(qualifier);
1428                 } else {
1429                     // Failure! Looks like the value is wrong, reset the qualifier
1430                     // Since the qualifier classes are immutable, and we don't want to
1431                     // remove the qualifier from the configuration, we create a new default one.
1432                     mSelectedConfiguration.setScreenDimensionQualifier(
1433                             new ScreenDimensionQualifier());
1434                 }
1435             }
1436 
1437             // notify of change
1438             onChange(true /* keepSelection */);
1439         }
1440 
1441         @Override
setQualifier(ResourceQualifier qualifier)1442         public void setQualifier(ResourceQualifier qualifier) {
1443             ScreenDimensionQualifier q = (ScreenDimensionQualifier)qualifier;
1444 
1445             mSize1.setText(Integer.toString(q.getValue1()));
1446             mSize2.setText(Integer.toString(q.getValue2()));
1447         }
1448     }
1449 
1450     /**
1451      * Edit widget for {@link VersionQualifier}.
1452      */
1453     private class VersionEdit extends QualifierEditBase {
1454         private Text mText;
1455 
VersionEdit(Composite parent)1456         public VersionEdit(Composite parent) {
1457             super(parent, VersionQualifier.NAME);
1458 
1459             mText = new Text(this, SWT.BORDER);
1460             mText.addVerifyListener(new MobileCodeVerifier());
1461             mText.addModifyListener(new ModifyListener() {
1462                 public void modifyText(ModifyEvent e) {
1463                     onVersionChange();
1464                 }
1465             });
1466             mText.addFocusListener(new FocusAdapter() {
1467                 @Override
1468                 public void focusLost(FocusEvent e) {
1469                     onVersionChange();
1470                 }
1471             });
1472 
1473             new Label(this, SWT.NONE).setText("(Platform API level)");
1474         }
1475 
onVersionChange()1476         private void onVersionChange() {
1477             String value = mText.getText();
1478 
1479             if (value.length() == 0) {
1480                 // empty string, means a qualifier with no value.
1481                 // Since the qualifier classes are immutable, and we don't want to
1482                 // remove the qualifier from the configuration, we create a new default one.
1483                 mSelectedConfiguration.setVersionQualifier(new VersionQualifier());
1484             } else {
1485                 try {
1486                     VersionQualifier qualifier = VersionQualifier.getQualifier(
1487                             VersionQualifier.getFolderSegment(Integer.parseInt(value)));
1488                     if (qualifier != null) {
1489                         mSelectedConfiguration.setVersionQualifier(qualifier);
1490                     } else {
1491                         // Failure! Looks like the value is wrong
1492                         mSelectedConfiguration.setVersionQualifier(new VersionQualifier());
1493                     }
1494                 } catch (NumberFormatException nfe) {
1495                     // Looks like the code is not a number. This should not happen since the text
1496                     // field has a VerifyListener that prevents it.
1497                     mSelectedConfiguration.setVersionQualifier(new VersionQualifier());
1498                 }
1499             }
1500 
1501             // notify of change
1502             onChange(true /* keepSelection */);
1503         }
1504 
1505         @Override
setQualifier(ResourceQualifier qualifier)1506         public void setQualifier(ResourceQualifier qualifier) {
1507             VersionQualifier q = (VersionQualifier)qualifier;
1508 
1509             mText.setText(Integer.toString(q.getVersion()));
1510         }
1511     }
1512 
1513 }
1514