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