• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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 
20 import static com.android.ide.common.resources.ResourceResolver.PREFIX_ANDROID_RESOURCE_REF;
21 import static com.android.ide.common.resources.ResourceResolver.PREFIX_RESOURCE_REF;
22 
23 import com.android.annotations.NonNull;
24 import com.android.ide.common.rendering.api.ResourceValue;
25 import com.android.ide.common.resources.ResourceItem;
26 import com.android.ide.common.resources.ResourceRepository;
27 import com.android.ide.common.resources.ResourceResolver;
28 import com.android.ide.eclipse.adt.AdtPlugin;
29 import com.android.ide.eclipse.adt.AdtUtils;
30 import com.android.ide.eclipse.adt.internal.assetstudio.OpenCreateAssetSetWizardAction;
31 import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
32 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart;
33 import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringRefactoring;
34 import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringWizard;
35 import com.android.ide.eclipse.adt.internal.resources.ResourceHelper;
36 import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator;
37 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
38 import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
39 import com.android.resources.ResourceType;
40 import com.android.util.Pair;
41 
42 import org.eclipse.core.resources.IFile;
43 import org.eclipse.core.resources.IProject;
44 import org.eclipse.core.resources.IResource;
45 import org.eclipse.core.runtime.IStatus;
46 import org.eclipse.core.runtime.Status;
47 import org.eclipse.jface.dialogs.IDialogConstants;
48 import org.eclipse.jface.dialogs.IInputValidator;
49 import org.eclipse.jface.dialogs.InputDialog;
50 import org.eclipse.jface.text.IRegion;
51 import org.eclipse.jface.window.Window;
52 import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
53 import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
54 import org.eclipse.swt.SWT;
55 import org.eclipse.swt.events.ModifyEvent;
56 import org.eclipse.swt.events.ModifyListener;
57 import org.eclipse.swt.events.SelectionAdapter;
58 import org.eclipse.swt.events.SelectionEvent;
59 import org.eclipse.swt.layout.GridData;
60 import org.eclipse.swt.layout.GridLayout;
61 import org.eclipse.swt.widgets.Button;
62 import org.eclipse.swt.widgets.Composite;
63 import org.eclipse.swt.widgets.Control;
64 import org.eclipse.swt.widgets.Event;
65 import org.eclipse.swt.widgets.Label;
66 import org.eclipse.swt.widgets.Listener;
67 import org.eclipse.swt.widgets.Shell;
68 import org.eclipse.swt.widgets.Text;
69 import org.eclipse.ui.IWorkbench;
70 import org.eclipse.ui.PlatformUI;
71 import org.eclipse.ui.dialogs.AbstractElementListSelectionDialog;
72 import org.eclipse.ui.dialogs.SelectionStatusDialog;
73 
74 import java.util.Arrays;
75 import java.util.Collection;
76 import java.util.Collections;
77 import java.util.List;
78 import java.util.Locale;
79 import java.util.regex.Matcher;
80 import java.util.regex.Pattern;
81 
82 /**
83  * A dialog to let the user select a resource based on a resource type.
84  */
85 public class ResourceChooser extends AbstractElementListSelectionDialog implements ModifyListener {
86     /** The return code from the dialog for the user choosing "Clear" */
87     public static final int CLEAR_RETURN_CODE = -5;
88     /** The dialog button ID for the user choosing "Clear" */
89     private static final int CLEAR_BUTTON_ID = CLEAR_RETURN_CODE;
90 
91     private Pattern mProjectResourcePattern;
92     private ResourceType mResourceType;
93     private final ResourceRepository mProjectResources;
94     private final ResourceRepository mFrameworkResources;
95     private Pattern mSystemResourcePattern;
96     private Button mProjectButton;
97     private Button mSystemButton;
98     private Button mNewButton;
99     private String mCurrentResource;
100     private final IProject mProject;
101     private IInputValidator mInputValidator;
102 
103     /** Helper object used to draw previews for drawables and colors. */
104     private ResourcePreviewHelper mPreviewHelper;
105 
106     /**
107      * Textfield for editing the actual returned value, updated when selection
108      * changes. Only shown if {@link #mShowValueText} is true.
109      */
110     private Text mEditValueText;
111 
112     /**
113      * Whether the {@link #mEditValueText} textfield should be shown when the dialog is created.
114      */
115     private boolean mShowValueText;
116 
117     /**
118      * Flag indicating whether it's the first time {@link #handleSelectionChanged()} is called.
119      * This is used to filter out the first selection event, always called by the superclass
120      * when the widget is created, to distinguish between "the dialog was created" and
121      * "the user clicked on a selection result", since only the latter should wipe out the
122      * manual user edit shown in the value text.
123      */
124     private boolean mFirstSelect = true;
125 
126     /**
127      * Label used to show the resolved value in the resource chooser. Only shown
128      * if the {@link #mResourceResolver} field is set.
129      */
130     private Label mResolvedLabel;
131 
132     /** Resource resolver used to show actual values for resources selected. (Optional). */
133     private ResourceResolver mResourceResolver;
134 
135     /**
136      * Creates a Resource Chooser dialog.
137      * @param project Project being worked on
138      * @param type The type of the resource to choose
139      * @param projectResources The repository for the project
140      * @param frameworkResources The Framework resource repository
141      * @param parent the parent shell
142      */
ResourceChooser(IProject project, ResourceType type, ResourceRepository projectResources, ResourceRepository frameworkResources, Shell parent)143     public ResourceChooser(IProject project, ResourceType type,
144             ResourceRepository projectResources,
145             ResourceRepository frameworkResources,
146             Shell parent) {
147         super(parent, new ResourceLabelProvider());
148         mProject = project;
149 
150         mResourceType = type;
151         mProjectResources = projectResources;
152         mFrameworkResources = frameworkResources;
153 
154         mProjectResourcePattern = Pattern.compile(
155                 PREFIX_RESOURCE_REF + mResourceType.getName() + "/(.+)"); //$NON-NLS-1$
156 
157         mSystemResourcePattern = Pattern.compile(
158                 PREFIX_ANDROID_RESOURCE_REF + mResourceType.getName() + "/(.+)"); //$NON-NLS-1$
159 
160         setTitle("Resource Chooser");
161         setMessage(String.format("Choose a %1$s resource",
162                 mResourceType.getDisplayName().toLowerCase(Locale.US)));
163     }
164 
165     /**
166      * Sets whether this dialog should show the value field as a separate text
167      * value (and take the resulting value of the dialog from this text field
168      * rather than from the selection)
169      *
170      * @param showValueText if true, show the value text field
171      */
setShowValueText(boolean showValueText)172     public void setShowValueText(boolean showValueText) {
173         mShowValueText = showValueText;
174     }
175 
176     /**
177      * Sets the resource resolver to use to show resolved values for the current
178      * selection
179      *
180      * @param resourceResolver the resource resolver to use
181      */
setResourceResolver(ResourceResolver resourceResolver)182     public void setResourceResolver(ResourceResolver resourceResolver) {
183         mResourceResolver = resourceResolver;
184     }
185 
186     /**
187      * Sets the {@link ResourcePreviewHelper} to use to preview drawable
188      * resources, if any
189      *
190      * @param previewHelper the helper to use
191      */
setPreviewHelper(ResourcePreviewHelper previewHelper)192     public void setPreviewHelper(ResourcePreviewHelper previewHelper) {
193         mPreviewHelper = previewHelper;
194     }
195 
196     @Override
create()197     public void create() {
198         super.create();
199 
200         if (mShowValueText) {
201             mEditValueText.selectAll();
202             mEditValueText.setFocus();
203         }
204     }
205 
206     @Override
createButtonsForButtonBar(Composite parent)207     protected void createButtonsForButtonBar(Composite parent) {
208         createButton(parent, CLEAR_BUTTON_ID, "Clear", false /*defaultButton*/);
209         super.createButtonsForButtonBar(parent);
210     }
211 
212     @Override
buttonPressed(int buttonId)213     protected void buttonPressed(int buttonId) {
214         super.buttonPressed(buttonId);
215 
216         if (buttonId == CLEAR_BUTTON_ID) {
217             assert CLEAR_RETURN_CODE != Window.OK && CLEAR_RETURN_CODE != Window.CANCEL;
218             setReturnCode(CLEAR_RETURN_CODE);
219             close();
220         }
221     }
222 
setCurrentResource(String resource)223     public void setCurrentResource(String resource) {
224         mCurrentResource = resource;
225 
226         if (mShowValueText && mEditValueText != null) {
227             mEditValueText.setText(resource);
228         }
229     }
230 
getCurrentResource()231     public String getCurrentResource() {
232         return mCurrentResource;
233     }
234 
setInputValidator(IInputValidator inputValidator)235     public void setInputValidator(IInputValidator inputValidator) {
236         mInputValidator = inputValidator;
237     }
238 
239     @Override
computeResult()240     protected void computeResult() {
241         if (mShowValueText) {
242             mCurrentResource = mEditValueText.getText();
243             if (mCurrentResource.length() == 0) {
244                 mCurrentResource = null;
245             }
246             return;
247         }
248 
249         computeResultFromSelection();
250     }
251 
computeResultFromSelection()252     private void computeResultFromSelection() {
253         if (getSelectionIndex() == -1) {
254             mCurrentResource = null;
255             return;
256         }
257 
258         Object[] elements = getSelectedElements();
259         if (elements.length == 1 && elements[0] instanceof ResourceItem) {
260             ResourceItem item = (ResourceItem)elements[0];
261 
262             mCurrentResource = item.getXmlString(mResourceType, mSystemButton.getSelection());
263 
264             if (mInputValidator != null && mInputValidator.isValid(mCurrentResource) != null) {
265                 mCurrentResource = null;
266             }
267         }
268     }
269 
270     @Override
createDialogArea(Composite parent)271     protected Control createDialogArea(Composite parent) {
272         Composite top = (Composite)super.createDialogArea(parent);
273 
274         createMessageArea(top);
275 
276         createButtons(top);
277         createFilterText(top);
278         createFilteredList(top);
279 
280         // create the "New Resource" button
281         createNewResButtons(top);
282 
283         // Optionally create the value text field, if {@link #mShowValueText} is true
284         createValueField(top);
285 
286         setupResourceList();
287         selectResourceString(mCurrentResource);
288 
289         return top;
290     }
291 
292     /**
293      * Creates the radio button to switch between project and system resources.
294      * @param top the parent composite
295      */
createButtons(Composite top)296     private void createButtons(Composite top) {
297         mProjectButton = new Button(top, SWT.RADIO);
298         mProjectButton.setText("Project Resources");
299         mProjectButton.addSelectionListener(new SelectionAdapter() {
300             @Override
301             public void widgetSelected(SelectionEvent e) {
302                 super.widgetSelected(e);
303                 if (mProjectButton.getSelection()) {
304                     // Clear selection before changing the list contents. This works around
305                     // a bug in the superclass where switching to the framework resources,
306                     // choosing one of the last resources, then switching to the project
307                     // resources would cause an exception when calling getSelection() because
308                     // selection state doesn't get cleared when we set new contents on
309                     // the filtered list.
310                     fFilteredList.setSelection(new int[0]);
311                     setupResourceList();
312                     updateNewButton(false /*isSystem*/);
313                     updateValue();
314                 }
315             }
316         });
317         mSystemButton = new Button(top, SWT.RADIO);
318         mSystemButton.setText("System Resources");
319         mSystemButton.addSelectionListener(new SelectionAdapter() {
320             @Override
321             public void widgetSelected(SelectionEvent e) {
322                 super.widgetSelected(e);
323                 if (mSystemButton.getSelection()) {
324                     fFilteredList.setSelection(new int[0]);
325                     setupResourceList();
326                     updateNewButton(true /*isSystem*/);
327                     updateValue();
328                 }
329             }
330         });
331     }
332 
333     /**
334      * Creates the "New Resource" button.
335      * @param top the parent composite
336      */
createNewResButtons(Composite top)337     private void createNewResButtons(Composite top) {
338         mNewButton = new Button(top, SWT.NONE);
339 
340         String title = String.format("New %1$s...", mResourceType.getDisplayName());
341         if (mResourceType == ResourceType.DRAWABLE) {
342             title = "Create New Icon...";
343         }
344         mNewButton.setText(title);
345 
346         mNewButton.addSelectionListener(new SelectionAdapter() {
347             @Override
348             public void widgetSelected(SelectionEvent e) {
349                 super.widgetSelected(e);
350 
351                 if (mResourceType == ResourceType.STRING) {
352                     // Special case: Use Extract String refactoring wizard UI
353                     String newName = createNewString();
354                     selectAddedItem(newName);
355                 } else if (mResourceType == ResourceType.DRAWABLE) {
356                     // Special case: Use the "Create Icon Set" wizard
357                     OpenCreateAssetSetWizardAction action =
358                             new OpenCreateAssetSetWizardAction(mProject);
359                     action.run();
360                     List<IResource> files = action.getCreatedFiles();
361                     if (files != null && files.size() > 0) {
362                         String newName = AdtUtils.stripAllExtensions(files.get(0).getName());
363                         // Recompute the "current resource" to select the new id
364                         ResourceItem[] items = setupResourceList();
365                         selectItemName(newName, items);
366                     }
367                 } else {
368                     if (ResourceHelper.isValueBasedResourceType(mResourceType)) {
369                         String newName = createNewValue(mResourceType);
370                         selectAddedItem(newName);
371                     } else {
372                         String newName = createNewFile(mResourceType);
373                         selectAddedItem(newName);
374                     }
375                 }
376             }
377 
378             private void selectAddedItem(String newName) {
379                 // Recompute the "current resource" to select the new id
380                 ResourceItem[] items = setupResourceList();
381 
382                 // Ensure that the name is in the list. There's a delay after
383                 // an item is added (until the builder runs and processes the delta)
384                 // so if it's not in the list, add it
385                 boolean found = false;
386                 for (ResourceItem item : items) {
387                     if (newName.equals(item.getName())) {
388                         found = true;
389                         break;
390                     }
391                 }
392                 if (!found) {
393                     ResourceItem[] newItems = new ResourceItem[items.length + 1];
394                     System.arraycopy(items, 0, newItems, 0, items.length);
395                     newItems[items.length] = new ResourceItem(newName);
396                     items = newItems;
397                     Arrays.sort(items);
398                     setListElements(items);
399                     fFilteredList.setEnabled(newItems.length > 0);
400                 }
401 
402                 selectItemName(newName, items);
403             }
404         });
405     }
406 
407     /**
408      * Creates the value text field.
409      *
410      * @param top the parent composite
411      */
createValueField(Composite top)412     private void createValueField(Composite top) {
413         if (mShowValueText) {
414             mEditValueText = new Text(top, SWT.BORDER);
415             if (mCurrentResource != null) {
416                 mEditValueText.setText(mCurrentResource);
417             }
418             mEditValueText.addModifyListener(this);
419 
420             GridData data = new GridData();
421             data.grabExcessVerticalSpace = false;
422             data.grabExcessHorizontalSpace = true;
423             data.horizontalAlignment = GridData.FILL;
424             data.verticalAlignment = GridData.BEGINNING;
425             mEditValueText.setLayoutData(data);
426             mEditValueText.setFont(top.getFont());
427         }
428 
429         if (mResourceResolver != null) {
430             mResolvedLabel = new Label(top, SWT.NONE);
431             GridData data = new GridData();
432             data.grabExcessVerticalSpace = false;
433             data.grabExcessHorizontalSpace = true;
434             data.horizontalAlignment = GridData.FILL;
435             data.verticalAlignment = GridData.BEGINNING;
436             mResolvedLabel.setLayoutData(data);
437         }
438     }
439 
updateResolvedLabel()440     private void updateResolvedLabel() {
441         if (mResourceResolver == null) {
442             return;
443         }
444 
445         String v = null;
446         if (mCurrentResource != null) {
447             v = mCurrentResource;
448             if (mCurrentResource.startsWith(PREFIX_RESOURCE_REF)) {
449                 ResourceValue value = mResourceResolver.findResValue(mCurrentResource, false);
450                 if (value != null) {
451                     v = value.getValue();
452                 }
453             }
454         }
455 
456         if (v == null) {
457             v = "";
458         }
459 
460         mResolvedLabel.setText(String.format("Resolved Value: %1$s", v));
461     }
462 
463     @Override
handleSelectionChanged()464     protected void handleSelectionChanged() {
465         super.handleSelectionChanged();
466         if (mInputValidator != null) {
467             Object[] elements = getSelectedElements();
468             if (elements.length == 1 && elements[0] instanceof ResourceItem) {
469                 ResourceItem item = (ResourceItem)elements[0];
470                 String current = item.getXmlString(mResourceType, mSystemButton.getSelection());
471                 String error = mInputValidator.isValid(current);
472                 IStatus status;
473                 if (error != null) {
474                     status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, error);
475                 } else {
476                     status = new Status(IStatus.OK, AdtPlugin.PLUGIN_ID, null);
477                 }
478                 updateStatus(status);
479             }
480         }
481 
482         updateValue();
483     }
484 
updateValue()485     private void updateValue() {
486         if (mPreviewHelper != null) {
487             computeResult();
488             mPreviewHelper.updatePreview(mResourceType, mCurrentResource);
489         }
490 
491         if (mShowValueText) {
492             if (mFirstSelect) {
493                 mFirstSelect = false;
494                 mEditValueText.selectAll();
495             } else {
496                 computeResultFromSelection();
497                 mEditValueText.setText(mCurrentResource != null ? mCurrentResource : "");
498             }
499         }
500 
501         if (mResourceResolver != null) {
502             if (!mShowValueText) {
503                 computeResultFromSelection();
504             }
505             updateResolvedLabel();
506         }
507     }
508 
createNewFile(ResourceType type)509     private String createNewFile(ResourceType type) {
510         // Show a name/value dialog entering the key name and the value
511         Shell shell = AdtPlugin.getDisplay().getActiveShell();
512         if (shell == null) {
513             return null;
514         }
515 
516         ResourceNameValidator validator = ResourceNameValidator.create(true /*allowXmlExtension*/,
517                 mProject, mResourceType);
518         InputDialog d = new InputDialog(
519                 AdtPlugin.getDisplay().getActiveShell(),
520                 "Enter name",  // title
521                 "Enter name",
522                 "", //$NON-NLS-1$
523                 validator);
524         if (d.open() == Window.OK) {
525             String name = d.getValue().trim();
526             if (name.length() == 0) {
527                 return null;
528             }
529 
530             Pair<IFile, IRegion> resource = ResourceHelper.createResource(mProject, type, name,
531                     null);
532             if (resource != null) {
533                 return name;
534             }
535         }
536 
537         return null;
538     }
539 
540 
createNewValue(ResourceType type)541     private String createNewValue(ResourceType type) {
542         // Show a name/value dialog entering the key name and the value
543         Shell shell = AdtPlugin.getDisplay().getActiveShell();
544         if (shell == null) {
545             return null;
546         }
547         NameValueDialog dialog = new NameValueDialog(shell, getFilter());
548         if (dialog.open() != Window.OK) {
549             return null;
550         }
551 
552         String name = dialog.getName();
553         String value = dialog.getValue();
554         if (name.length() == 0 || value.length() == 0) {
555             return null;
556         }
557 
558         Pair<IFile, IRegion> resource = ResourceHelper.createResource(mProject, type, name, value);
559         if (resource != null) {
560             return name;
561         }
562 
563         return null;
564     }
565 
createNewString()566     private String createNewString() {
567         ExtractStringRefactoring ref = new ExtractStringRefactoring(
568                 mProject, true /*enforceNew*/);
569         RefactoringWizard wizard = new ExtractStringWizard(ref, mProject);
570         RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard);
571         try {
572             IWorkbench w = PlatformUI.getWorkbench();
573             if (op.run(w.getDisplay().getActiveShell(), wizard.getDefaultPageTitle()) ==
574                     IDialogConstants.OK_ID) {
575                 return ref.getXmlStringId();
576             }
577         } catch (InterruptedException ex) {
578             // Interrupted. Pass.
579         }
580 
581         return null;
582     }
583 
584     /**
585      * Setups the current list.
586      */
setupResourceList()587     private ResourceItem[] setupResourceList() {
588         Collection<ResourceItem> items = null;
589         if (mProjectButton.getSelection()) {
590             items = mProjectResources.getResourceItemsOfType(mResourceType);
591         } else if (mSystemButton.getSelection()) {
592             items = mFrameworkResources.getResourceItemsOfType(mResourceType);
593         }
594 
595         if (items == null) {
596             items = Collections.emptyList();
597         }
598 
599         ResourceItem[] arrayItems = items.toArray(new ResourceItem[items.size()]);
600 
601         // sort the array
602         Arrays.sort(arrayItems);
603 
604         setListElements(arrayItems);
605         fFilteredList.setEnabled(arrayItems.length > 0);
606 
607         return arrayItems;
608     }
609 
610     /**
611      * Select an item by its name, if possible.
612      */
selectItemName(String itemName, ResourceItem[] items)613     private void selectItemName(String itemName, ResourceItem[] items) {
614         if (itemName == null || items == null) {
615             return;
616         }
617 
618         for (ResourceItem item : items) {
619             if (itemName.equals(item.getName())) {
620                 setSelection(new Object[] { item });
621                 break;
622             }
623         }
624     }
625 
626     /**
627      * Select an item by its full resource string.
628      * This also selects between project and system repository based on the resource string.
629      */
selectResourceString(String resourceString)630     private void selectResourceString(String resourceString) {
631         boolean isSystem = false;
632         String itemName = null;
633 
634         if (resourceString != null) {
635             // Is this a system resource?
636             // If not a system resource or if they are not available, this will be a project res.
637             Matcher m = mSystemResourcePattern.matcher(resourceString);
638             if (m.matches()) {
639                 itemName = m.group(1);
640                 isSystem = true;
641             }
642 
643             if (!isSystem && itemName == null) {
644                 // Try to match project resource name
645                 m = mProjectResourcePattern.matcher(resourceString);
646                 if (m.matches()) {
647                     itemName = m.group(1);
648                 }
649             }
650         }
651 
652         // Update the repository selection
653         mProjectButton.setSelection(!isSystem);
654         mSystemButton.setSelection(isSystem);
655         updateNewButton(isSystem);
656 
657         // Update the list
658         ResourceItem[] items = setupResourceList();
659 
660         // If we have a selection name, select it
661         if (itemName != null) {
662             selectItemName(itemName, items);
663         }
664     }
665 
updateNewButton(boolean isSystem)666     private void updateNewButton(boolean isSystem) {
667         mNewButton.setEnabled(!isSystem && ResourceHelper.canCreateResourceType(mResourceType));
668     }
669 
670     // ---- Implements ModifyListener ----
671 
672     @Override
modifyText(ModifyEvent e)673     public void modifyText(ModifyEvent e) {
674        if (e.getSource() == mEditValueText && mResourceResolver != null) {
675            mCurrentResource = mEditValueText.getText();
676 
677            if (mCurrentResource.startsWith(PREFIX_RESOURCE_REF)) {
678                if (mProjectResourcePattern.matcher(mCurrentResource).matches() ||
679                        mSystemResourcePattern.matcher(mCurrentResource).matches()) {
680                    updateResolvedLabel();
681                }
682            } else {
683                updateResolvedLabel();
684            }
685        }
686     }
687 
688     /** Dialog asking for a Name/Value pair */
689     private class NameValueDialog extends SelectionStatusDialog implements Listener {
690         private org.eclipse.swt.widgets.Text mNameText;
691         private org.eclipse.swt.widgets.Text mValueText;
692         private String mInitialName;
693         private String mName;
694         private String mValue;
695         private ResourceNameValidator mValidator;
696 
NameValueDialog(Shell parent, String initialName)697         public NameValueDialog(Shell parent, String initialName) {
698             super(parent);
699             mInitialName = initialName;
700         }
701 
702         @Override
createDialogArea(Composite parent)703         protected Control createDialogArea(Composite parent) {
704             Composite container = new Composite(parent, SWT.NONE);
705             container.setLayout(new GridLayout(2, false));
706             GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
707             // Wide enough to accommodate the error label
708             gridData.widthHint = 500;
709             container.setLayoutData(gridData);
710 
711 
712             Label nameLabel = new Label(container, SWT.NONE);
713             nameLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
714             nameLabel.setText("Name:");
715 
716             mNameText = new org.eclipse.swt.widgets.Text(container, SWT.BORDER);
717             mNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
718             if (mInitialName != null) {
719                 mNameText.setText(mInitialName);
720                 mNameText.selectAll();
721             }
722 
723             Label valueLabel = new Label(container, SWT.NONE);
724             valueLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
725             valueLabel.setText("Value:");
726 
727             mValueText = new org.eclipse.swt.widgets.Text(container, SWT.BORDER);
728             mValueText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
729 
730             mNameText.addListener(SWT.Modify, this);
731             mValueText.addListener(SWT.Modify, this);
732 
733             validate();
734 
735             return container;
736         }
737 
738         @Override
computeResult()739         protected void computeResult() {
740             mName = mNameText.getText().trim();
741             mValue = mValueText.getText().trim();
742         }
743 
getName()744         private String getName() {
745             return mName;
746         }
747 
getValue()748         private String getValue() {
749             return mValue;
750         }
751 
752         @Override
handleEvent(Event event)753         public void handleEvent(Event event) {
754             validate();
755         }
756 
validate()757         private void validate() {
758             IStatus status;
759             computeResult();
760             if (mName.length() == 0) {
761                 status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, "Enter a name");
762             } else if (mValue.length() == 0) {
763                 status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, "Enter a value");
764             } else {
765                 if (mValidator == null) {
766                     mValidator = ResourceNameValidator.create(false, mProject, mResourceType);
767                 }
768                 String error = mValidator.isValid(mName);
769                 if (error != null) {
770                     status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID, error);
771                 } else {
772                     status = new Status(IStatus.OK, AdtPlugin.PLUGIN_ID, null);
773                 }
774             }
775             updateStatus(status);
776         }
777     }
778 
779     /**
780      * Open the resource chooser for the given type, associated with the given
781      * editor
782      *
783      * @param graphicalEditor the editor associated with the resource to be
784      *            chosen (used to find the associated Android target to be used
785      *            for framework resources etc)
786      * @param type the resource type to be chosen
787      * @param currentValue the current value, or null
788      * @param validator a validator to be used, or null
789      * @return the chosen resource, null if cancelled and "" if value should be
790      *         cleared
791      */
chooseResource( @onNull GraphicalEditorPart graphicalEditor, @NonNull ResourceType type, String currentValue, IInputValidator validator)792     public static String chooseResource(
793             @NonNull GraphicalEditorPart graphicalEditor,
794             @NonNull ResourceType type,
795             String currentValue, IInputValidator validator) {
796         AndroidXmlEditor editor = graphicalEditor.getEditorDelegate().getEditor();
797         IProject project = editor.getProject();
798         if (project != null) {
799             // get the resource repository for this project and the system resources.
800             ResourceRepository projectRepository = ResourceManager.getInstance()
801                     .getProjectResources(project);
802             Shell shell = AdtPlugin.getDisplay().getActiveShell();
803             if (shell == null) {
804                 return null;
805             }
806 
807             AndroidTargetData data = editor.getTargetData();
808             ResourceRepository systemRepository = data.getFrameworkResources();
809 
810             // open a resource chooser dialog for specified resource type.
811             ResourceChooser dlg = new ResourceChooser(project, type, projectRepository,
812                     systemRepository, shell);
813             dlg.setPreviewHelper(new ResourcePreviewHelper(dlg, graphicalEditor));
814 
815             // When editing Strings, allow editing the value text directly. When we
816             // get inline editing support (where values entered directly into the
817             // textual widget are translated automatically into a resource) this can
818             // go away.
819             if (type == ResourceType.STRING) {
820                 dlg.setResourceResolver(graphicalEditor.getResourceResolver());
821                 dlg.setShowValueText(true);
822             } else if (type == ResourceType.DIMEN || type == ResourceType.INTEGER) {
823                 dlg.setResourceResolver(graphicalEditor.getResourceResolver());
824             }
825 
826             if (validator != null) {
827                 // Ensure wide enough to accommodate validator error message
828                 dlg.setSize(85, 10);
829                 dlg.setInputValidator(validator);
830             }
831 
832             dlg.setCurrentResource(currentValue);
833 
834             int result = dlg.open();
835             if (result == ResourceChooser.CLEAR_RETURN_CODE) {
836                 return ""; //$NON-NLS-1$
837             } else if (result == Window.OK) {
838                 return dlg.getCurrentResource();
839             }
840         }
841 
842         return null;
843     }
844 }
845