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:
Raphael Moll
2009-04-16 16:02:29 -07:00
committed by The Android Open Source Project
parent 568b71576e
commit 06803ce63d
4 changed files with 58 additions and 61 deletions

View File

@@ -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);
} }
/* /*
@@ -76,6 +80,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
* contains an SDK. * contains an SDK.
@@ -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;

View File

@@ -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());
} }

View File

@@ -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) {

View File

@@ -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);
@@ -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.
*/ */
@@ -191,16 +178,19 @@ public class SdkTargetSelector {
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()) {
@@ -336,6 +311,10 @@ public class SdkTargetSelector {
*/ */
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