AI 146634: am: CL 146631 ADT #1793333: fix Widget disposed in SdkTargetSelector.
This happens when you open the Windows > Prefs > Android panel while an SDK is initially loading or when you change the SDK in the pref panel. The target change listener was not properly removed since the field was not properly disposed. This also removed the multiple selection handling in the SdkTargetSelector, which we never use. In the unlikely event we want to use it later, it would be trivial to add it back. Original author: raphael Merged from: //branches/cupcake/... Automated import of CL 146634
This commit is contained in:
committed by
The Android Open Source Project
parent
568b71576e
commit
06803ce63d
@@ -50,6 +50,8 @@ import java.io.File;
|
|||||||
public class AndroidPreferencePage extends FieldEditorPreferencePage implements
|
public class AndroidPreferencePage extends FieldEditorPreferencePage implements
|
||||||
IWorkbenchPreferencePage {
|
IWorkbenchPreferencePage {
|
||||||
|
|
||||||
|
private SdkDirectoryFieldEditor mDirectoryField;
|
||||||
|
|
||||||
public AndroidPreferencePage() {
|
public AndroidPreferencePage() {
|
||||||
super(GRID);
|
super(GRID);
|
||||||
setPreferenceStore(AdtPlugin.getDefault().getPreferenceStore());
|
setPreferenceStore(AdtPlugin.getDefault().getPreferenceStore());
|
||||||
@@ -64,8 +66,10 @@ public class AndroidPreferencePage extends FieldEditorPreferencePage implements
|
|||||||
@Override
|
@Override
|
||||||
public void createFieldEditors() {
|
public void createFieldEditors() {
|
||||||
|
|
||||||
addField(new SdkDirectoryFieldEditor(AdtPlugin.PREFS_SDK_DIR,
|
mDirectoryField = new SdkDirectoryFieldEditor(AdtPlugin.PREFS_SDK_DIR,
|
||||||
Messages.AndroidPreferencePage_SDK_Location_, getFieldEditorParent()));
|
Messages.AndroidPreferencePage_SDK_Location_, getFieldEditorParent());
|
||||||
|
|
||||||
|
addField(mDirectoryField);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -75,6 +79,16 @@ public class AndroidPreferencePage extends FieldEditorPreferencePage implements
|
|||||||
*/
|
*/
|
||||||
public void init(IWorkbench workbench) {
|
public void init(IWorkbench workbench) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
|
||||||
|
if (mDirectoryField != null) {
|
||||||
|
mDirectoryField.dispose();
|
||||||
|
mDirectoryField = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom version of DirectoryFieldEditor which validates that the directory really
|
* Custom version of DirectoryFieldEditor which validates that the directory really
|
||||||
@@ -164,8 +178,7 @@ public class AndroidPreferencePage extends FieldEditorPreferencePage implements
|
|||||||
|
|
||||||
mTargetSelector = new SdkTargetSelector(parent,
|
mTargetSelector = new SdkTargetSelector(parent,
|
||||||
targets,
|
targets,
|
||||||
false, /*allowSelection*/
|
false /*allowSelection*/);
|
||||||
false /*multipleSelection*/);
|
|
||||||
gd = (GridData) mTargetSelector.getLayoutData();
|
gd = (GridData) mTargetSelector.getLayoutData();
|
||||||
gd.horizontalSpan = numColumns;
|
gd.horizontalSpan = numColumns;
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class AndroidPropertyPage extends PropertyPage implements IWorkbenchPrope
|
|||||||
Label l = new Label(top, SWT.NONE);
|
Label l = new Label(top, SWT.NONE);
|
||||||
l.setText("Project Target");
|
l.setText("Project Target");
|
||||||
|
|
||||||
mSelector = new SdkTargetSelector(top, targets, false /*allowMultipleSelection*/);
|
mSelector = new SdkTargetSelector(top, targets);
|
||||||
|
|
||||||
l = new Label(top, SWT.SEPARATOR | SWT.HORIZONTAL);
|
l = new Label(top, SWT.SEPARATOR | SWT.HORIZONTAL);
|
||||||
l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||||
@@ -98,7 +98,7 @@ public class AndroidPropertyPage extends PropertyPage implements IWorkbenchPrope
|
|||||||
@Override
|
@Override
|
||||||
public void widgetSelected(SelectionEvent e) {
|
public void widgetSelected(SelectionEvent e) {
|
||||||
// look for the selection and validate the page if there is a selection
|
// look for the selection and validate the page if there is a selection
|
||||||
IAndroidTarget target = mSelector.getFirstSelected();
|
IAndroidTarget target = mSelector.getSelected();
|
||||||
setValid(target != null);
|
setValid(target != null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -114,7 +114,7 @@ public class AndroidPropertyPage extends PropertyPage implements IWorkbenchPrope
|
|||||||
public boolean performOk() {
|
public boolean performOk() {
|
||||||
Sdk currentSdk = Sdk.getCurrent();
|
Sdk currentSdk = Sdk.getCurrent();
|
||||||
if (currentSdk != null) {
|
if (currentSdk != null) {
|
||||||
currentSdk.setProject(mProject, mSelector.getFirstSelected(),
|
currentSdk.setProject(mProject, mSelector.getSelected(),
|
||||||
mApkConfigWidget.getApkConfigs());
|
mApkConfigWidget.getApkConfigs());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ public class NewProjectCreationPage extends WizardPage {
|
|||||||
|
|
||||||
/** Returns the current sdk target or null if none has been selected yet. */
|
/** Returns the current sdk target or null if none has been selected yet. */
|
||||||
public IAndroidTarget getSdkTarget() {
|
public IAndroidTarget getSdkTarget() {
|
||||||
return mSdkTargetSelector == null ? null : mSdkTargetSelector.getFirstSelected();
|
return mSdkTargetSelector == null ? null : mSdkTargetSelector.getSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -405,7 +405,7 @@ public class NewProjectCreationPage extends WizardPage {
|
|||||||
group.setText("Target");
|
group.setText("Target");
|
||||||
|
|
||||||
// The selector is created without targets. They are added below in the change listener.
|
// The selector is created without targets. They are added below in the change listener.
|
||||||
mSdkTargetSelector = new SdkTargetSelector(group, null, false /*multi-selection*/);
|
mSdkTargetSelector = new SdkTargetSelector(group, null);
|
||||||
|
|
||||||
mSdkTargetChangeListener = new ITargetChangeListener() {
|
mSdkTargetChangeListener = new ITargetChangeListener() {
|
||||||
public void onProjectTargetChange(IProject changedProject) {
|
public void onProjectTargetChange(IProject changedProject) {
|
||||||
|
|||||||
@@ -43,14 +43,13 @@ import java.util.ArrayList;
|
|||||||
* <p/>
|
* <p/>
|
||||||
* To use, create it using {@link #SdkTargetSelector(Composite, IAndroidTarget[], boolean)} then
|
* To use, create it using {@link #SdkTargetSelector(Composite, IAndroidTarget[], boolean)} then
|
||||||
* call {@link #setSelection(IAndroidTarget)}, {@link #setSelectionListener(SelectionListener)}
|
* call {@link #setSelection(IAndroidTarget)}, {@link #setSelectionListener(SelectionListener)}
|
||||||
* and finally use {@link #getFirstSelected()} or {@link #getAllSelected()} to retrieve the
|
* and finally use {@link #getSelected()} to retrieve the
|
||||||
* selection.
|
* selection.
|
||||||
*/
|
*/
|
||||||
public class SdkTargetSelector {
|
public class SdkTargetSelector {
|
||||||
|
|
||||||
private IAndroidTarget[] mTargets;
|
private IAndroidTarget[] mTargets;
|
||||||
private final boolean mAllowSelection;
|
private final boolean mAllowSelection;
|
||||||
private final boolean mAllowMultipleSelection;
|
|
||||||
private SelectionListener mSelectionListener;
|
private SelectionListener mSelectionListener;
|
||||||
private Table mTable;
|
private Table mTable;
|
||||||
private Label mDescription;
|
private Label mDescription;
|
||||||
@@ -62,12 +61,9 @@ public class SdkTargetSelector {
|
|||||||
* @param parent The parent composite where the selector will be added.
|
* @param parent The parent composite where the selector will be added.
|
||||||
* @param targets The list of targets. This is <em>not</em> copied, the caller must not modify.
|
* @param targets The list of targets. This is <em>not</em> copied, the caller must not modify.
|
||||||
* Targets can be null or an empty array, in which case the table is disabled.
|
* Targets can be null or an empty array, in which case the table is disabled.
|
||||||
* @param allowMultipleSelection True if more than one SDK target can be selected at the same
|
|
||||||
* time.
|
|
||||||
*/
|
*/
|
||||||
public SdkTargetSelector(Composite parent, IAndroidTarget[] targets,
|
public SdkTargetSelector(Composite parent, IAndroidTarget[] targets) {
|
||||||
boolean allowMultipleSelection) {
|
this(parent, targets, true /*allowSelection*/);
|
||||||
this(parent, targets, true /*allowSelection*/, allowMultipleSelection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,12 +73,8 @@ public class SdkTargetSelector {
|
|||||||
* @param targets The list of targets. This is <em>not</em> copied, the caller must not modify.
|
* @param targets The list of targets. This is <em>not</em> copied, the caller must not modify.
|
||||||
* Targets can be null or an empty array, in which case the table is disabled.
|
* Targets can be null or an empty array, in which case the table is disabled.
|
||||||
* @param allowSelection True if selection is enabled.
|
* @param allowSelection True if selection is enabled.
|
||||||
* @param allowMultipleSelection True if more than one SDK target can be selected at the same
|
|
||||||
* time. Used only if allowSelection is true.
|
|
||||||
*/
|
*/
|
||||||
public SdkTargetSelector(Composite parent, IAndroidTarget[] targets,
|
public SdkTargetSelector(Composite parent, IAndroidTarget[] targets, boolean allowSelection) {
|
||||||
boolean allowSelection,
|
|
||||||
boolean allowMultipleSelection) {
|
|
||||||
// Layout has 1 column
|
// Layout has 1 column
|
||||||
mInnerGroup = new Composite(parent, SWT.NONE);
|
mInnerGroup = new Composite(parent, SWT.NONE);
|
||||||
mInnerGroup.setLayout(new GridLayout());
|
mInnerGroup.setLayout(new GridLayout());
|
||||||
@@ -90,13 +82,9 @@ public class SdkTargetSelector {
|
|||||||
mInnerGroup.setFont(parent.getFont());
|
mInnerGroup.setFont(parent.getFont());
|
||||||
|
|
||||||
mAllowSelection = allowSelection;
|
mAllowSelection = allowSelection;
|
||||||
mAllowMultipleSelection = allowMultipleSelection;
|
int style = SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION;
|
||||||
int style = SWT.BORDER;
|
|
||||||
if (allowSelection) {
|
if (allowSelection) {
|
||||||
style |= SWT.CHECK | SWT.FULL_SELECTION;
|
style |= SWT.CHECK;
|
||||||
}
|
|
||||||
if (!mAllowMultipleSelection) {
|
|
||||||
style |= SWT.SINGLE;
|
|
||||||
}
|
}
|
||||||
mTable = new Table(mInnerGroup, style);
|
mTable = new Table(mInnerGroup, style);
|
||||||
mTable.setHeaderVisible(true);
|
mTable.setHeaderVisible(true);
|
||||||
@@ -127,7 +115,7 @@ public class SdkTargetSelector {
|
|||||||
setTargets(targets);
|
setTargets(targets);
|
||||||
setupTooltip(mTable);
|
setupTooltip(mTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the layout data of the inner composite widget that contains the target selector.
|
* Returns the layout data of the inner composite widget that contains the target selector.
|
||||||
* By default the layout data is set to a {@link GridData} with a {@link GridData#FILL_BOTH}
|
* By default the layout data is set to a {@link GridData} with a {@link GridData#FILL_BOTH}
|
||||||
@@ -166,8 +154,7 @@ public class SdkTargetSelector {
|
|||||||
* The event's item contains a {@link TableItem}.
|
* The event's item contains a {@link TableItem}.
|
||||||
* The {@link TableItem#getData()} contains an {@link IAndroidTarget}.
|
* The {@link TableItem#getData()} contains an {@link IAndroidTarget}.
|
||||||
* <p/>
|
* <p/>
|
||||||
* It is recommended that the caller uses the {@link #getFirstSelected()} and
|
* It is recommended that the caller uses the {@link #getSelected()} method instead.
|
||||||
* {@link #getAllSelected()} methods instead.
|
|
||||||
*
|
*
|
||||||
* @param selectionListener The new listener or null to remove it.
|
* @param selectionListener The new listener or null to remove it.
|
||||||
*/
|
*/
|
||||||
@@ -188,19 +175,22 @@ public class SdkTargetSelector {
|
|||||||
if (!mAllowSelection) {
|
if (!mAllowSelection) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
for (TableItem i : mTable.getItems()) {
|
|
||||||
if ((IAndroidTarget) i.getData() == target) {
|
if (mTable != null && !mTable.isDisposed()) {
|
||||||
found = true;
|
for (TableItem i : mTable.getItems()) {
|
||||||
if (!i.getChecked()) {
|
if ((IAndroidTarget) i.getData() == target) {
|
||||||
|
found = true;
|
||||||
|
if (!i.getChecked()) {
|
||||||
|
modified = true;
|
||||||
|
i.setChecked(true);
|
||||||
|
}
|
||||||
|
} else if (i.getChecked()) {
|
||||||
modified = true;
|
modified = true;
|
||||||
i.setChecked(true);
|
i.setChecked(false);
|
||||||
}
|
}
|
||||||
} else if (i.getChecked()) {
|
|
||||||
modified = true;
|
|
||||||
i.setChecked(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,30 +202,15 @@ public class SdkTargetSelector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all selected items.
|
* Returns the selected item.
|
||||||
* This is useful when the table is in multiple-selection mode.
|
|
||||||
*
|
*
|
||||||
* @see #getFirstSelected()
|
* @return The selected item or null.
|
||||||
* @return An array of selected items. The list can be empty but not null.
|
|
||||||
*/
|
*/
|
||||||
public IAndroidTarget[] getAllSelected() {
|
public IAndroidTarget getSelected() {
|
||||||
ArrayList<IAndroidTarget> list = new ArrayList<IAndroidTarget>();
|
if (mTable == null || mTable.isDisposed()) {
|
||||||
for (TableItem i : mTable.getItems()) {
|
return null;
|
||||||
if (i.getChecked()) {
|
|
||||||
list.add((IAndroidTarget) i.getData());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return list.toArray(new IAndroidTarget[list.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the first selected item.
|
|
||||||
* This is useful when the table is in single-selection mode.
|
|
||||||
*
|
|
||||||
* @see #getAllSelected()
|
|
||||||
* @return The first selected item or null.
|
|
||||||
*/
|
|
||||||
public IAndroidTarget getFirstSelected() {
|
|
||||||
for (TableItem i : mTable.getItems()) {
|
for (TableItem i : mTable.getItems()) {
|
||||||
if (i.getChecked()) {
|
if (i.getChecked()) {
|
||||||
return (IAndroidTarget) i.getData();
|
return (IAndroidTarget) i.getData();
|
||||||
@@ -311,7 +286,7 @@ public class SdkTargetSelector {
|
|||||||
* items when this one is selected.
|
* items when this one is selected.
|
||||||
*/
|
*/
|
||||||
private void enforceSingleSelection(TableItem item) {
|
private void enforceSingleSelection(TableItem item) {
|
||||||
if (!mAllowMultipleSelection && item.getChecked()) {
|
if (item.getChecked()) {
|
||||||
Table parentTable = item.getParent();
|
Table parentTable = item.getParent();
|
||||||
for (TableItem i2 : parentTable.getItems()) {
|
for (TableItem i2 : parentTable.getItems()) {
|
||||||
if (i2 != item && i2.getChecked()) {
|
if (i2 != item && i2.getChecked()) {
|
||||||
@@ -335,7 +310,11 @@ public class SdkTargetSelector {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
private void fillTable(final Table table) {
|
private void fillTable(final Table table) {
|
||||||
|
|
||||||
|
if (table == null || table.isDisposed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
table.removeAll();
|
table.removeAll();
|
||||||
|
|
||||||
if (mTargets != null && mTargets.length > 0) {
|
if (mTargets != null && mTargets.length > 0) {
|
||||||
@@ -366,6 +345,11 @@ public class SdkTargetSelector {
|
|||||||
* display the description in a label under the table.
|
* display the description in a label under the table.
|
||||||
*/
|
*/
|
||||||
private void setupTooltip(final Table table) {
|
private void setupTooltip(final Table table) {
|
||||||
|
|
||||||
|
if (table == null || table.isDisposed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reference:
|
* Reference:
|
||||||
* http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet125.java?view=markup
|
* http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet125.java?view=markup
|
||||||
|
|||||||
Reference in New Issue
Block a user