aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ReferenceChooserDialog.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ReferenceChooserDialog.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ReferenceChooserDialog.java396
1 files changed, 396 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ReferenceChooserDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ReferenceChooserDialog.java
new file mode 100644
index 000000000..6c628658a
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ReferenceChooserDialog.java
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.internal.ui;
+
+import com.android.ide.common.resources.ResourceItem;
+import com.android.ide.common.resources.ResourceRepository;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.editors.layout.properties.PropertyFactory;
+import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringRefactoring;
+import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringWizard;
+import com.android.resources.ResourceType;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.DialogSettings;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.FilteredTree;
+import org.eclipse.ui.dialogs.PatternFilter;
+import org.eclipse.ui.dialogs.SelectionStatusDialog;
+
+import java.util.Collection;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A dialog to let the user choose a reference to a resource.
+ *
+ */
+public class ReferenceChooserDialog extends SelectionStatusDialog {
+
+ private static Pattern sResourcePattern = Pattern.compile("@(.*)/(.+)"); //$NON-NLS-1$
+ private static Pattern sInlineIdResourcePattern = Pattern.compile("@\\+id/(.+)"); //$NON-NLS-1$
+
+ private static IDialogSettings sDialogSettings = new DialogSettings("");
+
+ private ResourceRepository mProjectResources;
+ private String mCurrentResource;
+ private FilteredTree mFilteredTree;
+ private Button mNewResButton;
+ private final IProject mProject;
+ private TreeViewer mTreeViewer;
+ private ResourcePreviewHelper mPreviewHelper;
+
+ /**
+ * @param project
+ * @param parent
+ */
+ public ReferenceChooserDialog(IProject project, ResourceRepository projectResources,
+ Shell parent) {
+ super(parent);
+ mProject = project;
+ mProjectResources = projectResources;
+
+ int shellStyle = getShellStyle();
+ setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE);
+
+ setTitle("Reference Chooser");
+ setMessage(String.format("Choose a resource"));
+
+ setDialogBoundsSettings(sDialogSettings, getDialogBoundsStrategy());
+ }
+
+ public void setPreviewHelper(ResourcePreviewHelper previewHelper) {
+ mPreviewHelper = previewHelper;
+ }
+
+ public void setCurrentResource(String resource) {
+ mCurrentResource = resource;
+ }
+
+ public String getCurrentResource() {
+ return mCurrentResource;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.dialogs.SelectionStatusDialog#computeResult()
+ */
+ @Override
+ protected void computeResult() {
+ // get the selection
+ TreePath treeSelection = getSelection();
+ if (treeSelection != null) {
+ if (treeSelection.getSegmentCount() == 2) {
+ // get the resource type and the resource item
+ ResourceType resourceType = (ResourceType)treeSelection.getFirstSegment();
+ ResourceItem resourceItem = (ResourceItem)treeSelection.getLastSegment();
+
+ mCurrentResource = resourceItem.getXmlString(resourceType, false /* system */);
+ }
+ }
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite top = (Composite)super.createDialogArea(parent);
+
+ // create the standard message area
+ createMessageArea(top);
+
+ // create the filtered tree
+ createFilteredTree(top);
+
+ // setup the initial selection
+ if (mCurrentResource != null) {
+ setupInitialSelection();
+ }
+
+ // create the "New Resource" button
+ createNewResButtons(top);
+
+ Composite workaround = PropertyFactory.addWorkaround(top);
+ if (workaround != null) {
+ workaround.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1));
+ }
+
+ return top;
+ }
+
+ /**
+ * Creates the "New Resource" button.
+ * @param top the parent composite
+ */
+ private void createNewResButtons(Composite top) {
+ mNewResButton = new Button(top, SWT.NONE);
+ mNewResButton.addSelectionListener(new OnNewResButtonSelected());
+ updateNewResButton();
+ }
+
+ private void createFilteredTree(Composite parent) {
+ mFilteredTree = new FilteredTree(parent, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION,
+ new PatternFilter());
+
+ GridData data = new GridData();
+ data.widthHint = convertWidthInCharsToPixels(60);
+ data.heightHint = convertHeightInCharsToPixels(18);
+ data.grabExcessVerticalSpace = true;
+ data.grabExcessHorizontalSpace = true;
+ data.horizontalAlignment = GridData.FILL;
+ data.verticalAlignment = GridData.FILL;
+ mFilteredTree.setLayoutData(data);
+ mFilteredTree.setFont(parent.getFont());
+
+ mTreeViewer = mFilteredTree.getViewer();
+ Tree tree = mTreeViewer.getTree();
+
+ tree.addSelectionListener(new SelectionListener() {
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ handleDoubleClick();
+ }
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ handleSelection();
+ }
+ });
+
+ mTreeViewer.setLabelProvider(new ResourceLabelProvider());
+ mTreeViewer.setContentProvider(new ResourceContentProvider(false /* fullLevels */));
+ mTreeViewer.setInput(mProjectResources);
+ }
+
+ protected void handleSelection() {
+ validateCurrentSelection();
+ updateNewResButton();
+
+ if (mPreviewHelper != null) {
+ TreePath treeSelection = getSelection();
+ ResourceType type = null;
+ if (treeSelection != null && treeSelection.getSegmentCount() == 2) {
+ Object segment = treeSelection.getSegment(0);
+ if (segment instanceof ResourceType) {
+ type = (ResourceType) segment;
+ // Ensure that mCurrentResource is valid
+ computeResult();
+ }
+ }
+
+ mPreviewHelper.updatePreview(type, mCurrentResource);
+ }
+ }
+
+ protected void handleDoubleClick() {
+ if (validateCurrentSelection()) {
+ buttonPressed(IDialogConstants.OK_ID);
+ }
+ }
+
+ /**
+ * Returns the selected item in the tree as a {@link TreePath} object.
+ * @return the <code>TreePath</code> object or <code>null</code> if there was no selection.
+ */
+ private TreePath getSelection() {
+ ISelection selection = mFilteredTree.getViewer().getSelection();
+ if (selection instanceof TreeSelection) {
+ TreeSelection treeSelection = (TreeSelection)selection;
+ TreePath[] treePaths = treeSelection.getPaths();
+
+ // the selection mode is SWT.SINGLE, so we just get the first one.
+ if (treePaths.length > 0) {
+ return treePaths[0];
+ }
+ }
+
+ return null;
+ }
+
+ private boolean validateCurrentSelection() {
+ TreePath treeSelection = getSelection();
+
+ IStatus status;
+ if (treeSelection != null) {
+ if (treeSelection.getSegmentCount() == 2) {
+ status = new Status(IStatus.OK, AdtPlugin.PLUGIN_ID,
+ IStatus.OK, "", //$NON-NLS-1$
+ null);
+ } else {
+ status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
+ IStatus.ERROR, "You must select a Resource Item",
+ null);
+ }
+ } else {
+ status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
+ IStatus.ERROR, "", //$NON-NLS-1$
+ null);
+ }
+
+ updateStatus(status);
+
+ return status.isOK();
+ }
+
+ /**
+ * Updates the new res button when the list selection changes.
+ * The name of the button changes depending on the resource.
+ */
+ private void updateNewResButton() {
+ ResourceType type = getSelectedResourceType();
+
+ // We only support adding new strings right now
+ mNewResButton.setEnabled(type == ResourceType.STRING);
+
+ String title = String.format("New %1$s...",
+ type == null ? "Resource" : type.getDisplayName());
+ mNewResButton.setText(title);
+ mNewResButton.pack();
+ }
+
+ /**
+ * Callback invoked when the mNewResButton is selected by the user.
+ */
+ private class OnNewResButtonSelected extends SelectionAdapter {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ super.widgetSelected(e);
+
+ ResourceType type = getSelectedResourceType();
+
+ // We currently only support strings
+ if (type == ResourceType.STRING) {
+
+ ExtractStringRefactoring ref = new ExtractStringRefactoring(
+ mProject, true /*enforceNew*/);
+ RefactoringWizard wizard = new ExtractStringWizard(ref, mProject);
+ RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard);
+ try {
+ IWorkbench w = PlatformUI.getWorkbench();
+ if (op.run(w.getDisplay().getActiveShell(), wizard.getDefaultPageTitle()) ==
+ IDialogConstants.OK_ID) {
+ mTreeViewer.refresh();
+
+ // select it if possible
+ setupInitialSelection(type, ref.getXmlStringId());
+ }
+ } catch (InterruptedException ex) {
+ // Interrupted. Pass.
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the {@link ResourceType} of the selected element, if any.
+ * Returns null if nothing suitable is selected.
+ */
+ private ResourceType getSelectedResourceType() {
+ ResourceType type = null;
+
+ TreePath selection = getSelection();
+ if (selection != null && selection.getSegmentCount() > 0) {
+ Object first = selection.getFirstSegment();
+ if (first instanceof ResourceType) {
+ type = (ResourceType) first;
+ }
+ }
+ return type;
+ }
+
+ /**
+ * Sets up the initial selection.
+ * <p/>
+ * This parses {@link #mCurrentResource} to find out the resource type and the resource name.
+ */
+ private void setupInitialSelection() {
+ // checks the inline id pattern first as it's more restrictive than the other one.
+ Matcher m = sInlineIdResourcePattern.matcher(mCurrentResource);
+ if (m.matches()) {
+ // get the matching name
+ String resourceName = m.group(1);
+
+ // setup initial selection
+ setupInitialSelection(ResourceType.ID, resourceName);
+ } else {
+ // attempts the inline id pattern
+ m = sResourcePattern.matcher(mCurrentResource);
+ if (m.matches()) {
+ // get the resource type.
+ ResourceType resourceType = ResourceType.getEnum(m.group(1));
+ if (resourceType != null) {
+ // get the matching name
+ String resourceName = m.group(2);
+
+ // setup initial selection
+ setupInitialSelection(resourceType, resourceName);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets up the initial selection based on a {@link ResourceType} and a resource name.
+ * @param resourceType the resource type.
+ * @param resourceName the resource name.
+ */
+ private void setupInitialSelection(ResourceType resourceType, String resourceName) {
+ // get all the resources of this type
+ Collection<ResourceItem> resourceItems =
+ mProjectResources.getResourceItemsOfType(resourceType);
+
+ for (ResourceItem resourceItem : resourceItems) {
+ if (resourceName.equals(resourceItem.getName())) {
+ // name of the resource match, we select it,
+ TreePath treePath = new TreePath(new Object[] { resourceType, resourceItem });
+ mFilteredTree.getViewer().setSelection(
+ new TreeSelection(treePath),
+ true /*reveal*/);
+
+ // and we're done.
+ return;
+ }
+ }
+
+ // if we get here, the resource type is valid, but the resource is missing.
+ // we select and expand the resource type element.
+ TreePath treePath = new TreePath(new Object[] { resourceType });
+ mFilteredTree.getViewer().setSelection(
+ new TreeSelection(treePath),
+ true /*reveal*/);
+ mFilteredTree.getViewer().setExpandedState(resourceType, true /* expanded */);
+ }
+}