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