OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / sdk / eclipse / plugins / com.android.ide.eclipse.adt / src / com / android / ide / eclipse / adt / internal / preferences / AndroidPreferencePage.java
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.eclipse.org/org/documents/epl-v10.php
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.ide.eclipse.adt.internal.preferences;
18
19 import com.android.ide.eclipse.adt.AdtPlugin;
20 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
21 import com.android.ide.eclipse.adt.internal.sdk.Sdk.ITargetChangeListener;
22 import com.android.sdklib.IAndroidTarget;
23 import com.android.sdkuilib.internal.widgets.SdkTargetSelector;
24
25 import org.eclipse.core.resources.IProject;
26 import org.eclipse.jface.preference.DirectoryFieldEditor;
27 import org.eclipse.jface.preference.FieldEditorPreferencePage;
28 import org.eclipse.jface.resource.JFaceResources;
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.layout.GridData;
31 import org.eclipse.swt.widgets.Composite;
32 import org.eclipse.swt.widgets.Label;
33 import org.eclipse.swt.widgets.Text;
34 import org.eclipse.ui.IWorkbench;
35 import org.eclipse.ui.IWorkbenchPreferencePage;
36
37 import java.io.File;
38
39 /**
40  * This class represents a preference page that is contributed to the
41  * Preferences dialog. By subclassing <samp>FieldEditorPreferencePage</samp>,
42  * we can use the field support built into JFace that allows us to create a page
43  * that is small and knows how to save, restore and apply itself.
44  * <p>
45  * This page is used to modify preferences only. They are stored in the
46  * preference store that belongs to the main plug-in class. That way,
47  * preferences can be accessed directly via the preference store.
48  */
49
50 public class AndroidPreferencePage extends FieldEditorPreferencePage implements
51         IWorkbenchPreferencePage {
52
53     private SdkDirectoryFieldEditor mDirectoryField;
54
55     public AndroidPreferencePage() {
56         super(GRID);
57         setPreferenceStore(AdtPlugin.getDefault().getPreferenceStore());
58         setDescription(Messages.AndroidPreferencePage_Title);
59     }
60
61     /**
62      * Creates the field editors. Field editors are abstractions of the common
63      * GUI blocks needed to manipulate various types of preferences. Each field
64      * editor knows how to save and restore itself.
65      */
66     @Override
67     public void createFieldEditors() {
68
69         mDirectoryField = new SdkDirectoryFieldEditor(AdtPrefs.PREFS_SDK_DIR,
70                 Messages.AndroidPreferencePage_SDK_Location_, getFieldEditorParent());
71
72         addField(mDirectoryField);
73     }
74
75     /*
76      * (non-Javadoc)
77      *
78      * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
79      */
80     public void init(IWorkbench workbench) {
81     }
82
83     @Override
84     public void dispose() {
85         super.dispose();
86
87         if (mDirectoryField != null) {
88             mDirectoryField.dispose();
89             mDirectoryField = null;
90         }
91     }
92
93     /**
94      * Custom version of DirectoryFieldEditor which validates that the directory really
95      * contains an SDK.
96      *
97      * There's a known issue here, which is really a rare edge-case: if the pref dialog is open
98      * which a given sdk directory and the *content* of the directory changes such that the sdk
99      * state changed (i.e. from valid to invalid or vice versa), the pref panel will display or
100      * hide the error as appropriate but the pref panel will fail to validate the apply/ok buttons
101      * appropriately. The easy workaround is to cancel the pref panel and enter it again.
102      */
103     private static class SdkDirectoryFieldEditor extends DirectoryFieldEditor {
104
105         private SdkTargetSelector mTargetSelector;
106         private TargetChangedListener mTargetChangeListener;
107
108         public SdkDirectoryFieldEditor(String name, String labelText, Composite parent) {
109             super(name, labelText, parent);
110             setEmptyStringAllowed(false);
111         }
112
113         /**
114          * Method declared on StringFieldEditor and overridden in DirectoryFieldEditor.
115          * Checks whether the text input field contains a valid directory.
116          *
117          * @return True if the apply/ok button should be enabled in the pref panel
118          */
119         @Override
120         protected boolean doCheckState() {
121             String fileName = getTextControl().getText();
122             fileName = fileName.trim();
123
124             if (fileName.indexOf(',') >= 0 || fileName.indexOf(';') >= 0) {
125                 setErrorMessage(Messages.AndroidPreferencePage_ERROR_Reserved_Char);
126                 return false;  // Apply/OK must be disabled
127             }
128
129             File file = new File(fileName);
130             if (!file.isDirectory()) {
131                 setErrorMessage(JFaceResources.getString(
132                     "DirectoryFieldEditor.errorMessage")); //$NON-NLS-1$
133                 return false;
134             }
135
136             boolean ok = AdtPlugin.getDefault().checkSdkLocationAndId(fileName,
137                     new AdtPlugin.CheckSdkErrorHandler() {
138                 @Override
139                 public boolean handleError(String message) {
140                     setErrorMessage(message.replaceAll("\n", " ")); //$NON-NLS-1$ //$NON-NLS-2$
141                     return false;  // Apply/OK must be disabled
142                 }
143
144                 @Override
145                 public boolean handleWarning(String message) {
146                     showMessage(message.replaceAll("\n", " ")); //$NON-NLS-1$ //$NON-NLS-2$
147                     return true;  // Apply/OK must be enabled
148                 }
149             });
150             if (ok) clearMessage();
151             return ok;
152         }
153
154         @Override
155         public Text getTextControl(Composite parent) {
156             setValidateStrategy(VALIDATE_ON_KEY_STROKE);
157             return super.getTextControl(parent);
158         }
159
160         /* (non-Javadoc)
161          * Method declared on StringFieldEditor (and FieldEditor).
162          */
163         @Override
164         protected void doFillIntoGrid(Composite parent, int numColumns) {
165             super.doFillIntoGrid(parent, numColumns);
166
167             GridData gd;
168             Label l = new Label(parent, SWT.NONE);
169             l.setText("Note: The list of SDK Targets below is only reloaded once you hit 'Apply' or 'OK'.");
170             gd = new GridData(GridData.FILL_HORIZONTAL);
171             gd.horizontalSpan = numColumns;
172             l.setLayoutData(gd);
173
174             try {
175                 // We may not have an sdk if the sdk path pref is empty or not valid.
176                 Sdk sdk = Sdk.getCurrent();
177                 IAndroidTarget[] targets = sdk != null ? sdk.getTargets() : null;
178
179                 mTargetSelector = new SdkTargetSelector(parent,
180                         targets,
181                         false /*allowSelection*/);
182                 gd = (GridData) mTargetSelector.getLayoutData();
183                 gd.horizontalSpan = numColumns;
184
185                 if (mTargetChangeListener == null) {
186                     mTargetChangeListener = new TargetChangedListener();
187                     AdtPlugin.getDefault().addTargetListener(mTargetChangeListener);
188                 }
189             } catch (Exception e) {
190                 // We need to catch *any* exception that arises here, otherwise it disables
191                 // the whole pref panel. We can live without the Sdk target selector but
192                 // not being able to actually set an sdk path.
193                 AdtPlugin.log(e, "SdkTargetSelector failed");
194             }
195         }
196
197         @Override
198         public void dispose() {
199             super.dispose();
200             if (mTargetChangeListener != null) {
201                 AdtPlugin.getDefault().removeTargetListener(mTargetChangeListener);
202                 mTargetChangeListener = null;
203             }
204         }
205
206         private class TargetChangedListener implements ITargetChangeListener {
207             public void onSdkLoaded() {
208                 if (mTargetSelector != null) {
209                     // We may not have an sdk if the sdk path pref is empty or not valid.
210                     Sdk sdk = Sdk.getCurrent();
211                     IAndroidTarget[] targets = sdk != null ? sdk.getTargets() : null;
212
213                     mTargetSelector.setTargets(targets);
214                 }
215             }
216
217             public void onProjectTargetChange(IProject changedProject) {
218                 // do nothing.
219             }
220
221             public void onTargetLoaded(IAndroidTarget target) {
222                 // do nothing.
223             }
224         }
225     }
226 }