Merge change 770 into donut
* changes: ADT 1603194: Android Package browser for Instrumentation nodes.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package com.android.ide.eclipse.adt.wizards.actions;
|
||||
|
||||
import org.eclipse.jface.action.IAction;
|
||||
import org.eclipse.jface.dialogs.Dialog;
|
||||
import org.eclipse.jface.viewers.ISelection;
|
||||
import org.eclipse.jface.viewers.IStructuredSelection;
|
||||
import org.eclipse.jface.viewers.StructuredSelection;
|
||||
@@ -52,6 +53,21 @@ import org.eclipse.ui.internal.util.Util;
|
||||
*/
|
||||
private static final int SIZING_WIZARD_HEIGHT = 500;
|
||||
|
||||
/** The wizard that was created by {@link #run(IAction)}. */
|
||||
private IWorkbenchWizard mWizard;
|
||||
/** The result from the dialog */
|
||||
private int mDialogResult;
|
||||
|
||||
/** Returns the wizard that was created by {@link #run(IAction)}. */
|
||||
public IWorkbenchWizard getWizard() {
|
||||
return mWizard;
|
||||
}
|
||||
|
||||
/** Returns the result from {@link Dialog#open()}, available after
|
||||
* the completion of {@link #run(IAction)}. */
|
||||
public int getDialogResult() {
|
||||
return mDialogResult;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose()
|
||||
@@ -72,6 +88,7 @@ import org.eclipse.ui.internal.util.Util;
|
||||
* <p/>
|
||||
* Most of this implementation is extracted from {@link NewWizardShortcutAction#run()}.
|
||||
*
|
||||
* @param action The action that got us here. Can be null when used internally.
|
||||
* @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
|
||||
*/
|
||||
public void run(IAction action) {
|
||||
@@ -102,12 +119,12 @@ import org.eclipse.ui.internal.util.Util;
|
||||
}
|
||||
|
||||
// Create the wizard and initialize it with the selection
|
||||
IWorkbenchWizard wizard = instanciateWizard(action);
|
||||
wizard.init(workbench, selectionToPass);
|
||||
mWizard = instanciateWizard(action);
|
||||
mWizard.init(workbench, selectionToPass);
|
||||
|
||||
// It's not visible yet until a dialog is created and opened
|
||||
Shell parent = window.getShell();
|
||||
WizardDialog dialog = new WizardDialog(parent, wizard);
|
||||
WizardDialog dialog = new WizardDialog(parent, mWizard);
|
||||
dialog.create();
|
||||
|
||||
// This code comes straight from NewWizardShortcutAction#run()
|
||||
@@ -118,13 +135,14 @@ import org.eclipse.ui.internal.util.Util;
|
||||
window.getWorkbench().getHelpSystem().setHelp(dialog.getShell(),
|
||||
IWorkbenchHelpContextIds.NEW_WIZARD_SHORTCUT);
|
||||
|
||||
dialog.open();
|
||||
mDialogResult = dialog.open();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by {@link #run(IAction)} to instantiate the actual wizard.
|
||||
*
|
||||
* @param action The action parameter from {@link #run(IAction)}.
|
||||
* This can be null.
|
||||
* @return A new wizard instance. Must not be null.
|
||||
*/
|
||||
protected abstract IWorkbenchWizard instanciateWizard(IAction action);
|
||||
|
||||
@@ -143,6 +143,8 @@ public class NewProjectWizard extends Wizard implements INewWizard {
|
||||
protected static final String MAIN_PAGE_NAME = "newAndroidProjectPage"; //$NON-NLS-1$
|
||||
|
||||
private NewProjectCreationPage mMainPage;
|
||||
/** Package name available when the wizard completes. */
|
||||
private String mPackageName;
|
||||
|
||||
/**
|
||||
* Initializes this creation wizard using the passed workbench and object
|
||||
@@ -203,6 +205,13 @@ public class NewProjectWizard extends Wizard implements INewWizard {
|
||||
return true;
|
||||
}
|
||||
|
||||
// -- Public Fields --
|
||||
|
||||
/** Returns the package name. Only valid once the wizard finishes. */
|
||||
public String getPackageName() {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
// -- Custom Methods --
|
||||
|
||||
/**
|
||||
@@ -234,16 +243,20 @@ public class NewProjectWizard extends Wizard implements INewWizard {
|
||||
final IProject project = workspace.getRoot().getProject(mMainPage.getProjectName());
|
||||
final IProjectDescription description = workspace.newProjectDescription(project.getName());
|
||||
|
||||
|
||||
// keep some variables to make them available once the wizard closes
|
||||
mPackageName = mMainPage.getPackageName();
|
||||
|
||||
final Map<String, Object> parameters = new HashMap<String, Object>();
|
||||
parameters.put(PARAM_PROJECT, mMainPage.getProjectName());
|
||||
parameters.put(PARAM_PACKAGE, mMainPage.getPackageName());
|
||||
parameters.put(PARAM_PACKAGE, mPackageName);
|
||||
parameters.put(PARAM_APPLICATION, STRING_RSRC_PREFIX + STRING_APP_NAME);
|
||||
parameters.put(PARAM_SDK_TOOLS_DIR, AdtPlugin.getOsSdkToolsFolder());
|
||||
parameters.put(PARAM_IS_NEW_PROJECT, mMainPage.isNewProject());
|
||||
parameters.put(PARAM_SRC_FOLDER, mMainPage.getSourceFolder());
|
||||
parameters.put(PARAM_SDK_TARGET, mMainPage.getSdkTarget());
|
||||
parameters.put(PARAM_MIN_SDK_VERSION, mMainPage.getMinSdkVersion());
|
||||
|
||||
|
||||
if (mMainPage.isCreateActivity()) {
|
||||
// An activity name can be of the form ".package.Class" or ".Class".
|
||||
// The initial dot is ignored, as it is always added later in the templates.
|
||||
|
||||
@@ -55,8 +55,10 @@ import javax.xml.xpath.XPathExpressionException;
|
||||
* Multi-page form editor for AndroidManifest.xml.
|
||||
*/
|
||||
public final class ManifestEditor extends AndroidEditor {
|
||||
private final static String EMPTY = ""; //$NON-NLS-1$
|
||||
|
||||
public static final String ID = AndroidConstants.EDITORS_NAMESPACE + ".manifest.ManifestEditor"; //$NON-NLS-1$
|
||||
|
||||
private final static String EMPTY = ""; //$NON-NLS-1$
|
||||
|
||||
/** Root node of the UI element hierarchy */
|
||||
private UiElementNode mUiManifestNode;
|
||||
|
||||
@@ -193,7 +193,7 @@ public final class AndroidManifestDescriptors implements IDescriptorProvider {
|
||||
|
||||
overrides.put("*/theme", ThemeAttributeDescriptor.class); //$NON-NLS-1$
|
||||
overrides.put("*/permission", ListAttributeDescriptor.class); //$NON-NLS-1$
|
||||
overrides.put("*/targetPackage", PackageAttributeDescriptor.class); //$NON-NLS-1$
|
||||
overrides.put("*/targetPackage", ManifestPkgAttrDescriptor.class); //$NON-NLS-1$
|
||||
|
||||
overrides.put("uses-library/name", ListAttributeDescriptor.class); //$NON-NLS-1$
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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.editors.manifest.descriptors;
|
||||
|
||||
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
|
||||
import com.android.ide.eclipse.editors.manifest.model.UiManifestPkgAttrNode;
|
||||
import com.android.ide.eclipse.editors.uimodel.UiAttributeNode;
|
||||
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
|
||||
|
||||
/**
|
||||
* Describes a package XML attribute. It is displayed by a {@link UiManifestPkgAttrNode}.
|
||||
*/
|
||||
public class ManifestPkgAttrDescriptor extends TextAttributeDescriptor {
|
||||
|
||||
public ManifestPkgAttrDescriptor(String xmlLocalName, String uiName, String nsUri,
|
||||
String tooltip) {
|
||||
super(xmlLocalName, uiName, nsUri, tooltip);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A new {@link UiManifestPkgAttrNode} linked to this descriptor.
|
||||
*/
|
||||
@Override
|
||||
public UiAttributeNode createUiNode(UiElementNode uiParent) {
|
||||
return new UiManifestPkgAttrNode(this, uiParent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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.editors.manifest.model;
|
||||
|
||||
import com.android.ide.eclipse.adt.AdtPlugin;
|
||||
import com.android.ide.eclipse.adt.wizards.actions.NewProjectAction;
|
||||
import com.android.ide.eclipse.adt.wizards.newproject.NewProjectWizard;
|
||||
import com.android.ide.eclipse.common.project.AndroidManifestParser;
|
||||
import com.android.ide.eclipse.common.project.BaseProjectHelper;
|
||||
import com.android.ide.eclipse.editors.descriptors.AttributeDescriptor;
|
||||
import com.android.ide.eclipse.editors.descriptors.TextAttributeDescriptor;
|
||||
import com.android.ide.eclipse.editors.manifest.ManifestEditor;
|
||||
import com.android.ide.eclipse.editors.ui.SectionHelper;
|
||||
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
|
||||
import com.android.ide.eclipse.editors.uimodel.UiTextAttributeNode;
|
||||
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jface.dialogs.Dialog;
|
||||
import org.eclipse.jface.dialogs.IMessageProvider;
|
||||
import org.eclipse.jface.viewers.ILabelProvider;
|
||||
import org.eclipse.jface.viewers.ILabelProviderListener;
|
||||
import org.eclipse.jface.window.Window;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.DisposeEvent;
|
||||
import org.eclipse.swt.events.DisposeListener;
|
||||
import org.eclipse.swt.events.ModifyEvent;
|
||||
import org.eclipse.swt.events.ModifyListener;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
import org.eclipse.ui.IWorkbenchPage;
|
||||
import org.eclipse.ui.IWorkbenchWindow;
|
||||
import org.eclipse.ui.PartInitException;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
|
||||
import org.eclipse.ui.forms.IManagedForm;
|
||||
import org.eclipse.ui.forms.events.HyperlinkAdapter;
|
||||
import org.eclipse.ui.forms.events.HyperlinkEvent;
|
||||
import org.eclipse.ui.forms.widgets.FormText;
|
||||
import org.eclipse.ui.forms.widgets.FormToolkit;
|
||||
import org.eclipse.ui.forms.widgets.TableWrapData;
|
||||
import org.eclipse.ui.part.FileEditorInput;
|
||||
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* Represents an XML attribute to select an exisintg manifest package, that can be modified using
|
||||
* a simple text field or a dialog to choose an existing package.
|
||||
* <p/>
|
||||
* See {@link UiTextAttributeNode} for more information.
|
||||
*/
|
||||
public class UiManifestPkgAttrNode extends UiTextAttributeNode {
|
||||
|
||||
/**
|
||||
* Creates a {@link UiManifestPkgAttrNode} object that will display ui to select or create
|
||||
* a manifest package.
|
||||
* @param attributeDescriptor the {@link AttributeDescriptor} object linked to the Ui Node.
|
||||
*/
|
||||
public UiManifestPkgAttrNode(AttributeDescriptor attributeDescriptor, UiElementNode uiParent) {
|
||||
super(attributeDescriptor, uiParent);
|
||||
}
|
||||
|
||||
/* (non-java doc)
|
||||
* Creates a label widget and an associated text field.
|
||||
* <p/>
|
||||
* As most other parts of the android manifest editor, this assumes the
|
||||
* parent uses a table layout with 2 columns.
|
||||
*/
|
||||
@Override
|
||||
public void createUiControl(final Composite parent, final IManagedForm managedForm) {
|
||||
setManagedForm(managedForm);
|
||||
FormToolkit toolkit = managedForm.getToolkit();
|
||||
TextAttributeDescriptor desc = (TextAttributeDescriptor) getDescriptor();
|
||||
|
||||
StringBuilder label = new StringBuilder();
|
||||
label.append("<form><p><a href='unused'>"); //$NON-NLS-1$
|
||||
label.append(desc.getUiName());
|
||||
label.append("</a></p></form>"); //$NON-NLS-1$
|
||||
FormText formText = SectionHelper.createFormText(parent, toolkit, true /* isHtml */,
|
||||
label.toString(), true /* setupLayoutData */);
|
||||
formText.addHyperlinkListener(new HyperlinkAdapter() {
|
||||
@Override
|
||||
public void linkActivated(HyperlinkEvent e) {
|
||||
super.linkActivated(e);
|
||||
doLabelClick();
|
||||
}
|
||||
});
|
||||
formText.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.MIDDLE));
|
||||
SectionHelper.addControlTooltip(formText, desc.getTooltip());
|
||||
|
||||
Composite composite = toolkit.createComposite(parent);
|
||||
composite.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE));
|
||||
GridLayout gl = new GridLayout(2, false);
|
||||
gl.marginHeight = gl.marginWidth = 0;
|
||||
composite.setLayout(gl);
|
||||
// Fixes missing text borders under GTK... also requires adding a 1-pixel margin
|
||||
// for the text field below
|
||||
toolkit.paintBordersFor(composite);
|
||||
|
||||
final Text text = toolkit.createText(composite, getCurrentValue());
|
||||
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
|
||||
gd.horizontalIndent = 1; // Needed by the fixed composite borders under GTK
|
||||
text.setLayoutData(gd);
|
||||
|
||||
setTextWidget(text);
|
||||
|
||||
Button browseButton = toolkit.createButton(composite, "Browse...", SWT.PUSH);
|
||||
|
||||
browseButton.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
super.widgetSelected(e);
|
||||
doBrowseClick();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/* (non-java doc)
|
||||
* Adds a validator to the text field that calls managedForm.getMessageManager().
|
||||
*/
|
||||
@Override
|
||||
protected void onAddValidators(final Text text) {
|
||||
ModifyListener listener = new ModifyListener() {
|
||||
public void modifyText(ModifyEvent e) {
|
||||
String package_name = text.getText();
|
||||
if (package_name.indexOf('.') < 1) {
|
||||
getManagedForm().getMessageManager().addMessage(text,
|
||||
"Package name should contain at least two identifiers.",
|
||||
null /* data */, IMessageProvider.ERROR, text);
|
||||
} else {
|
||||
getManagedForm().getMessageManager().removeMessage(text, text);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
text.addModifyListener(listener);
|
||||
|
||||
// Make sure the validator removes its message(s) when the widget is disposed
|
||||
text.addDisposeListener(new DisposeListener() {
|
||||
public void widgetDisposed(DisposeEvent e) {
|
||||
getManagedForm().getMessageManager().removeMessage(text, text);
|
||||
}
|
||||
});
|
||||
|
||||
// Finally call the validator once to make sure the initial value is processed
|
||||
listener.modifyText(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles response to the Browse button by creating a Package dialog.
|
||||
* */
|
||||
private void doBrowseClick() {
|
||||
|
||||
// Display the list of AndroidManifest packages in a selection dialog
|
||||
ElementListSelectionDialog dialog = new ElementListSelectionDialog(
|
||||
getTextWidget().getShell(),
|
||||
new ILabelProvider() {
|
||||
public Image getImage(Object element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getText(Object element) {
|
||||
return element.toString();
|
||||
}
|
||||
|
||||
public void addListener(ILabelProviderListener listener) {
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
public boolean isLabelProperty(Object element, String property) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeListener(ILabelProviderListener listener) {
|
||||
}
|
||||
});
|
||||
|
||||
dialog.setTitle("Android Manifest Package Selection");
|
||||
dialog.setMessage("Select the Android Manifest package to target.");
|
||||
|
||||
dialog.setElements(getPossibleValues(null));
|
||||
|
||||
// open the dialog and use the object selected if OK was clicked, or null otherwise
|
||||
if (dialog.open() == Window.OK) {
|
||||
String result = (String) dialog.getFirstResult();
|
||||
if (result != null && result.length() > 0) {
|
||||
getTextWidget().setText(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles response to the Label hyper link being activated.
|
||||
*/
|
||||
private void doLabelClick() {
|
||||
// get the current package name
|
||||
String package_name = getTextWidget().getText().trim();
|
||||
|
||||
if (package_name.length() == 0) {
|
||||
createNewProject();
|
||||
} else {
|
||||
displayExistingManifest(package_name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When the label is clicked and there's already a package name, this method
|
||||
* attempts to find the project matching the android package name and it attempts
|
||||
* to open the manifest editor.
|
||||
*
|
||||
* @param package_name The android package name to find. Must not be null.
|
||||
*/
|
||||
private void displayExistingManifest(String package_name) {
|
||||
|
||||
// Look for the first project that uses this package name
|
||||
for (IJavaProject project : BaseProjectHelper.getAndroidProjects()) {
|
||||
// check that there is indeed a manifest file.
|
||||
IFile manifestFile = AndroidManifestParser.getManifest(project.getProject());
|
||||
if (manifestFile == null) {
|
||||
// no file? skip this project.
|
||||
continue;
|
||||
}
|
||||
|
||||
AndroidManifestParser parser = null;
|
||||
try {
|
||||
parser = AndroidManifestParser.parseForData(manifestFile);
|
||||
} catch (CoreException e) {
|
||||
// ignore, handled below.
|
||||
}
|
||||
if (parser == null) {
|
||||
// skip this project.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (package_name.equals(parser.getPackage())) {
|
||||
// Found the project.
|
||||
|
||||
IWorkbenchWindow win = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
|
||||
if (win != null) {
|
||||
IWorkbenchPage page = win.getActivePage();
|
||||
if (page != null) {
|
||||
try {
|
||||
page.openEditor(
|
||||
new FileEditorInput(manifestFile),
|
||||
ManifestEditor.ID,
|
||||
true, /* activate */
|
||||
IWorkbenchPage.MATCH_INPUT);
|
||||
} catch (PartInitException e) {
|
||||
AdtPlugin.log(e,
|
||||
"Opening editor failed for %s", //$NON-NLS-1$
|
||||
manifestFile.getFullPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We found the project; even if we failed there's no need to keep looking.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the New Project Wizard to create a new project.
|
||||
* If one is successfully created, use the Android Package name.
|
||||
*/
|
||||
private void createNewProject() {
|
||||
|
||||
NewProjectAction npwAction = new NewProjectAction();
|
||||
npwAction.run(null /*action*/);
|
||||
if (npwAction.getDialogResult() == Dialog.OK) {
|
||||
NewProjectWizard npw = (NewProjectWizard) npwAction.getWizard();
|
||||
String name = npw.getPackageName();
|
||||
if (name != null && name.length() > 0) {
|
||||
getTextWidget().setText(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the possible android package names that could be used.
|
||||
* The prefix is not used.
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String[] getPossibleValues(String prefix) {
|
||||
TreeSet<String> packages = new TreeSet<String>();
|
||||
|
||||
for (IJavaProject project : BaseProjectHelper.getAndroidProjects()) {
|
||||
// check that there is indeed a manifest file.
|
||||
IFile manifestFile = AndroidManifestParser.getManifest(project.getProject());
|
||||
if (manifestFile == null) {
|
||||
// no file? skip this project.
|
||||
continue;
|
||||
}
|
||||
|
||||
AndroidManifestParser parser = null;
|
||||
try {
|
||||
parser = AndroidManifestParser.parseForData(manifestFile);
|
||||
} catch (CoreException e) {
|
||||
// ignore, handled below.
|
||||
}
|
||||
if (parser == null) {
|
||||
// skip this project.
|
||||
continue;
|
||||
}
|
||||
|
||||
packages.add(parser.getPackage());
|
||||
}
|
||||
|
||||
return packages.toArray(new String[packages.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user