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