diff options
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java')
-rw-r--r-- | eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java new file mode 100644 index 000000000..4fbc01351 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2007 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.preferences; + +import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler; +import com.android.ide.eclipse.adt.internal.sdk.Sdk; +import com.android.ide.eclipse.adt.internal.sdk.Sdk.ITargetChangeListener; +import com.android.sdklib.IAndroidTarget; +import com.android.sdkstats.DdmsPreferenceStore; +import com.android.sdkstats.SdkStatsService; +import com.android.sdkuilib.internal.widgets.SdkTargetSelector; + +import org.eclipse.core.resources.IProject; +import org.eclipse.jface.preference.DirectoryFieldEditor; +import org.eclipse.jface.preference.FieldEditorPreferencePage; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPreferencePage; + +import java.io.File; + +/** + * This class represents a preference page that is contributed to the + * Preferences dialog. By subclassing <samp>FieldEditorPreferencePage</samp>, + * we can use the field support built into JFace that allows us to create a page + * that is small and knows how to save, restore and apply itself. + * <p> + * This page is used to modify preferences only. They are stored in the + * preference store that belongs to the main plug-in class. That way, + * preferences can be accessed directly via the preference store. + */ + +public class AndroidPreferencePage extends FieldEditorPreferencePage implements + IWorkbenchPreferencePage { + + private SdkDirectoryFieldEditor mDirectoryField; + + public AndroidPreferencePage() { + super(GRID); + setPreferenceStore(AdtPlugin.getDefault().getPreferenceStore()); + setDescription(Messages.AndroidPreferencePage_Title); + } + + /** + * Creates the field editors. Field editors are abstractions of the common + * GUI blocks needed to manipulate various types of preferences. Each field + * editor knows how to save and restore itself. + */ + @Override + public void createFieldEditors() { + + mDirectoryField = new SdkDirectoryFieldEditor(AdtPrefs.PREFS_SDK_DIR, + Messages.AndroidPreferencePage_SDK_Location_, getFieldEditorParent()); + + addField(mDirectoryField); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench) + */ + @Override + 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 + * contains an SDK. + * + * There's a known issue here, which is really a rare edge-case: if the pref dialog is open + * which a given sdk directory and the *content* of the directory changes such that the sdk + * state changed (i.e. from valid to invalid or vice versa), the pref panel will display or + * hide the error as appropriate but the pref panel will fail to validate the apply/ok buttons + * appropriately. The easy workaround is to cancel the pref panel and enter it again. + */ + private static class SdkDirectoryFieldEditor extends DirectoryFieldEditor { + + private SdkTargetSelector mTargetSelector; + private TargetChangedListener mTargetChangeListener; + + public SdkDirectoryFieldEditor(String name, String labelText, Composite parent) { + super(name, labelText, parent); + setEmptyStringAllowed(false); + } + + /** + * Method declared on StringFieldEditor and overridden in DirectoryFieldEditor. + * Checks whether the text input field contains a valid directory. + * + * @return True if the apply/ok button should be enabled in the pref panel + */ + @Override + protected boolean doCheckState() { + String fileName = getTextControl().getText(); + fileName = fileName.trim(); + + if (fileName.indexOf(',') >= 0 || fileName.indexOf(';') >= 0) { + setErrorMessage(Messages.AndroidPreferencePage_ERROR_Reserved_Char); + return false; // Apply/OK must be disabled + } + + File file = new File(fileName); + if (!file.isDirectory()) { + setErrorMessage(JFaceResources.getString( + "DirectoryFieldEditor.errorMessage")); //$NON-NLS-1$ + return false; + } + + boolean ok = AdtPlugin.getDefault().checkSdkLocationAndId(fileName, + new AdtPlugin.CheckSdkErrorHandler() { + @Override + public boolean handleError( + CheckSdkErrorHandler.Solution solution, + String message) { + setErrorMessage(message.replaceAll("\n", " ")); //$NON-NLS-1$ //$NON-NLS-2$ + return false; // Apply/OK must be disabled + } + + @Override + public boolean handleWarning( + CheckSdkErrorHandler.Solution solution, + String message) { + showMessage(message.replaceAll("\n", " ")); //$NON-NLS-1$ //$NON-NLS-2$ + return true; // Apply/OK must be enabled + } + }); + if (ok) clearMessage(); + return ok; + } + + @Override + protected void doStore() { + super.doStore(); + + // Also sync the value to the ~/.android preference settings such that we can + // share it with future new workspaces + String path = AdtPrefs.getPrefs().getOsSdkFolder(); + if (path != null && path.length() > 0 && new File(path).exists()) { + DdmsPreferenceStore ddmsStore = new DdmsPreferenceStore(); + ddmsStore.setLastSdkPath(path); + } + } + + @Override + public Text getTextControl(Composite parent) { + setValidateStrategy(VALIDATE_ON_KEY_STROKE); + return super.getTextControl(parent); + } + + /* (non-Javadoc) + * Method declared on StringFieldEditor (and FieldEditor). + */ + @Override + protected void doFillIntoGrid(Composite parent, int numColumns) { + super.doFillIntoGrid(parent, numColumns); + + GridData gd; + Label l = new Label(parent, SWT.NONE); + l.setText("Note: The list of SDK Targets below is only reloaded once you hit 'Apply' or 'OK'."); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = numColumns; + l.setLayoutData(gd); + + try { + // We may not have an sdk if the sdk path pref is empty or not valid. + Sdk sdk = Sdk.getCurrent(); + IAndroidTarget[] targets = sdk != null ? sdk.getTargets() : null; + + mTargetSelector = new SdkTargetSelector(parent, + targets, + false /*allowSelection*/); + gd = (GridData) mTargetSelector.getLayoutData(); + gd.horizontalSpan = numColumns; + + if (mTargetChangeListener == null) { + mTargetChangeListener = new TargetChangedListener(); + AdtPlugin.getDefault().addTargetListener(mTargetChangeListener); + + // Trigger a check to see if the SDK needs to be reloaded (which will + // invoke onSdkLoaded asynchronously as needed). + AdtPlugin.getDefault().refreshSdk(); + } + } catch (Exception e) { + // We need to catch *any* exception that arises here, otherwise it disables + // the whole pref panel. We can live without the Sdk target selector but + // not being able to actually set an sdk path. + AdtPlugin.log(e, "SdkTargetSelector failed"); + } + } + + @Override + public void dispose() { + super.dispose(); + if (mTargetChangeListener != null) { + AdtPlugin.getDefault().removeTargetListener(mTargetChangeListener); + mTargetChangeListener = null; + } + } + + private class TargetChangedListener implements ITargetChangeListener { + @Override + public void onSdkLoaded() { + if (mTargetSelector != null) { + // We may not have an sdk if the sdk path pref is empty or not valid. + Sdk sdk = Sdk.getCurrent(); + IAndroidTarget[] targets = sdk != null ? sdk.getTargets() : null; + + mTargetSelector.setTargets(targets); + } + } + + @Override + public void onProjectTargetChange(IProject changedProject) { + // do nothing. + } + + @Override + public void onTargetLoaded(IAndroidTarget target) { + // do nothing. + } + } + } + + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + + /* When the ADT preferences page is made visible, display the dialog to obtain + * permissions for the ping service. */ + SdkStatsService stats = new SdkStatsService(); + Shell parent = getShell(); + stats.checkUserPermissionForPing(parent); + } +} |