• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 
20 import com.android.ide.eclipse.adt.AdtPlugin;
21 import com.android.ide.eclipse.adt.internal.editors.formatting.XmlFormatStyle;
22 import com.android.prefs.AndroidLocation.AndroidLocationException;
23 import com.android.sdklib.internal.build.DebugKeyProvider;
24 import com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException;
25 import com.android.sdkstats.DdmsPreferenceStore;
26 
27 import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
28 import org.eclipse.jface.preference.IPreferenceStore;
29 import org.eclipse.jface.util.PropertyChangeEvent;
30 
31 import java.io.File;
32 
33 public final class AdtPrefs extends AbstractPreferenceInitializer {
34     public final static String PREFS_SDK_DIR = AdtPlugin.PLUGIN_ID + ".sdk"; //$NON-NLS-1$
35 
36     public final static String PREFS_BUILD_RES_AUTO_REFRESH = AdtPlugin.PLUGIN_ID + ".resAutoRefresh"; //$NON-NLS-1$
37 
38     public final static String PREFS_BUILD_FORCE_ERROR_ON_NATIVELIB_IN_JAR = AdtPlugin.PLUGIN_ID + ".forceErrorNativeLibInJar"; //$NON-NLS-1$
39 
40     public final static String PREFS_BUILD_SKIP_POST_COMPILE_ON_FILE_SAVE = AdtPlugin.PLUGIN_ID + ".skipPostCompileOnFileSave"; //$NON-NLS-1$
41 
42     public final static String PREFS_BUILD_VERBOSITY = AdtPlugin.PLUGIN_ID + ".buildVerbosity"; //$NON-NLS-1$
43 
44     public final static String PREFS_DEFAULT_DEBUG_KEYSTORE = AdtPlugin.PLUGIN_ID + ".defaultDebugKeyStore"; //$NON-NLS-1$
45 
46     public final static String PREFS_CUSTOM_DEBUG_KEYSTORE = AdtPlugin.PLUGIN_ID + ".customDebugKeyStore"; //$NON-NLS-1$
47 
48     public final static String PREFS_HOME_PACKAGE = AdtPlugin.PLUGIN_ID + ".homePackage"; //$NON-NLS-1$
49 
50     public final static String PREFS_EMU_OPTIONS = AdtPlugin.PLUGIN_ID + ".emuOptions"; //$NON-NLS-1$
51 
52     public final static String PREFS_MONITOR_DENSITY = AdtPlugin.PLUGIN_ID + ".monitorDensity"; //$NON-NLS-1$
53 
54     public final static String PREFS_FORMAT_GUI_XML = AdtPlugin.PLUGIN_ID + ".formatXml"; //$NON-NLS-1$
55     public final static String PREFS_USE_CUSTOM_XML_FORMATTER = AdtPlugin.PLUGIN_ID + ".androidForm"; //$NON-NLS-1$
56 
57     public final static String PREFS_PALETTE_MODE = AdtPlugin.PLUGIN_ID + ".palette"; //$NON-NLS-1$
58 
59     public final static String PREFS_USE_ECLIPSE_INDENT = AdtPlugin.PLUGIN_ID + ".eclipseIndent"; //$NON-NLS-1$
60     public final static String PREVS_REMOVE_EMPTY_LINES = AdtPlugin.PLUGIN_ID + ".removeEmpty"; //$NON-NLS-1$
61     public final static String PREFS_ONE_ATTR_PER_LINE = AdtPlugin.PLUGIN_ID + ".oneAttrPerLine"; //$NON-NLS-1$
62     public final static String PREFS_SPACE_BEFORE_CLOSE = AdtPlugin.PLUGIN_ID + ".spaceBeforeClose"; //$NON-NLS-1$
63     public final static String PREFS_FORMAT_ON_SAVE = AdtPlugin.PLUGIN_ID + ".formatOnSave"; //$NON-NLS-1$
64     public final static String PREFS_ATTRIBUTE_SORT = AdtPlugin.PLUGIN_ID + ".attrSort"; //$NON-NLS-1$
65 
66     /** singleton instance */
67     private final static AdtPrefs sThis = new AdtPrefs();
68 
69     /** default store, provided by eclipse */
70     private IPreferenceStore mStore;
71 
72     /** cached location for the sdk folder */
73     private String mOsSdkLocation;
74 
75     /** Verbosity of the build */
76     private BuildVerbosity mBuildVerbosity = BuildVerbosity.NORMAL;
77 
78     private boolean mBuildForceResResfresh = false;
79     private boolean mBuildForceErrorOnNativeLibInJar = true;
80     private boolean mBuildSkipPostCompileOnFileSave = true;
81     private float mMonitorDensity = 0.f;
82     private String mPalette;
83 
84     private boolean mFormatGuiXml;
85     private boolean mCustomXmlFormatter;
86     private boolean mUseEclipseIndent;
87     private boolean mRemoveEmptyLines;
88     private boolean mOneAttributeOnFirstLine;
89     private boolean mSpaceBeforeClose;
90     private boolean mFormatOnSave;
91     private AttributeSortOrder mAttributeSort;
92 
93     public static enum BuildVerbosity {
94         /** Build verbosity "Always". Those messages are always displayed, even in silent mode */
95         ALWAYS(0),
96         /** Build verbosity level "Normal" */
97         NORMAL(1),
98         /** Build verbosity level "Verbose". Those messages are only displayed in verbose mode */
99         VERBOSE(2);
100 
101         private int mLevel;
102 
BuildVerbosity(int level)103         BuildVerbosity(int level) {
104             mLevel = level;
105         }
106 
getLevel()107         public int getLevel() {
108             return mLevel;
109         }
110 
111         /**
112          * Finds and returns a {@link BuildVerbosity} whose {@link #name()} matches a given name.
113          * <p/>This is different from {@link Enum#valueOf(Class, String)} in that it returns null
114          * if no matches are found.
115          *
116          * @param name the name to look up.
117          * @return returns the matching enum or null of no match where found.
118          */
find(String name)119         public static BuildVerbosity find(String name) {
120             for (BuildVerbosity v : values()) {
121                 if (v.name().equals(name)) {
122                     return v;
123                 }
124             }
125 
126             return null;
127         }
128     }
129 
init(IPreferenceStore preferenceStore)130     public static void init(IPreferenceStore preferenceStore) {
131         sThis.mStore = preferenceStore;
132     }
133 
getPrefs()134     public static AdtPrefs getPrefs() {
135         return sThis;
136     }
137 
loadValues(PropertyChangeEvent event)138     public synchronized void loadValues(PropertyChangeEvent event) {
139         // get the name of the property that changed, if any
140         String property = event != null ? event.getProperty() : null;
141 
142         if (property == null || PREFS_SDK_DIR.equals(property)) {
143             mOsSdkLocation = mStore.getString(PREFS_SDK_DIR);
144 
145             // Make it possible to override the SDK path using an environment variable.
146             // The value will only be used if it matches an existing directory.
147             // Useful for testing from Eclipse.
148             // Note: this is a hack that does not change the preferences, so if the user
149             // looks at Window > Preferences > Android, the path will be the preferences
150             // one and not the overridden one.
151             String override = System.getenv("ADT_TEST_SDK_PATH");   //$NON-NLS-1$
152             if (override != null && override.length() > 0 && new File(override).isDirectory()) {
153                 mOsSdkLocation = override;
154             }
155 
156             // make sure it ends with a separator. Normally this is done when the preference
157             // is set. But to make sure older version still work, we fix it here as well.
158             if (mOsSdkLocation.length() > 0 && mOsSdkLocation.endsWith(File.separator) == false) {
159                 mOsSdkLocation = mOsSdkLocation + File.separator;
160             }
161         }
162 
163         if (property == null || PREFS_BUILD_VERBOSITY.equals(property)) {
164             mBuildVerbosity = BuildVerbosity.find(mStore.getString(PREFS_BUILD_VERBOSITY));
165             if (mBuildVerbosity == null) {
166                 mBuildVerbosity = BuildVerbosity.NORMAL;
167             }
168         }
169 
170         if (property == null || PREFS_BUILD_RES_AUTO_REFRESH.equals(property)) {
171             mBuildForceResResfresh = mStore.getBoolean(PREFS_BUILD_RES_AUTO_REFRESH);
172         }
173 
174         if (property == null || PREFS_BUILD_FORCE_ERROR_ON_NATIVELIB_IN_JAR.equals(property)) {
175             mBuildForceErrorOnNativeLibInJar = mStore.getBoolean(PREFS_BUILD_RES_AUTO_REFRESH);
176         }
177 
178         if (property == null || PREFS_BUILD_SKIP_POST_COMPILE_ON_FILE_SAVE.equals(property)) {
179             mBuildSkipPostCompileOnFileSave =
180                 mStore.getBoolean(PREFS_BUILD_SKIP_POST_COMPILE_ON_FILE_SAVE);
181         }
182 
183         if (property == null || PREFS_MONITOR_DENSITY.equals(property)) {
184             mMonitorDensity = mStore.getFloat(PREFS_MONITOR_DENSITY);
185         }
186 
187         if (property == null || PREFS_FORMAT_GUI_XML.equals(property)) {
188             mFormatGuiXml = mStore.getBoolean(PREFS_FORMAT_GUI_XML);
189         }
190 
191         if (property == null || PREFS_USE_CUSTOM_XML_FORMATTER.equals(property)) {
192             mCustomXmlFormatter = mStore.getBoolean(PREFS_USE_CUSTOM_XML_FORMATTER);
193         }
194 
195         if (property == null || PREFS_PALETTE_MODE.equals(property)) {
196             mPalette = mStore.getString(PREFS_PALETTE_MODE);
197         }
198 
199         if (property == null || PREFS_USE_ECLIPSE_INDENT.equals(property)) {
200             mUseEclipseIndent = mStore.getBoolean(PREFS_USE_ECLIPSE_INDENT);
201         }
202 
203         if (property == null || PREVS_REMOVE_EMPTY_LINES.equals(property)) {
204             mRemoveEmptyLines = mStore.getBoolean(PREVS_REMOVE_EMPTY_LINES);
205         }
206 
207         if (property == null || PREFS_ONE_ATTR_PER_LINE.equals(property)) {
208             mOneAttributeOnFirstLine = mStore.getBoolean(PREFS_ONE_ATTR_PER_LINE);
209         }
210 
211         if (property == null || PREFS_ATTRIBUTE_SORT.equals(property)) {
212             String order = mStore.getString(PREFS_ATTRIBUTE_SORT);
213             mAttributeSort = AttributeSortOrder.LOGICAL;
214             if (AttributeSortOrder.ALPHABETICAL.key.equals(order)) {
215                 mAttributeSort = AttributeSortOrder.ALPHABETICAL;
216             } else if (AttributeSortOrder.NO_SORTING.key.equals(order)) {
217                 mAttributeSort = AttributeSortOrder.NO_SORTING;
218             }
219         }
220 
221         if (property == null || PREFS_SPACE_BEFORE_CLOSE.equals(property)) {
222             mSpaceBeforeClose = mStore.getBoolean(PREFS_SPACE_BEFORE_CLOSE);
223         }
224 
225         if (property == null || PREFS_FORMAT_ON_SAVE.equals(property)) {
226             mFormatOnSave = mStore.getBoolean(PREFS_FORMAT_ON_SAVE);
227         }
228     }
229 
230     /**
231      * Returns the SDK folder.
232      * Guaranteed to be terminated by a platform-specific path separator.
233      */
getOsSdkFolder()234     public synchronized String getOsSdkFolder() {
235         return mOsSdkLocation;
236     }
237 
getBuildVerbosity()238     public synchronized BuildVerbosity getBuildVerbosity() {
239         return mBuildVerbosity;
240     }
241 
getBuildForceResResfresh()242     public boolean getBuildForceResResfresh() {
243         return mBuildForceResResfresh;
244     }
245 
246     /**
247      * Should changes made by GUI editors automatically format the corresponding XML nodes
248      * affected by the edit?
249      *
250      * @return true if the GUI editors should format affected XML regions
251      */
getFormatGuiXml()252     public boolean getFormatGuiXml() {
253         // The format-GUI-editors flag only applies when the custom formatter is used,
254         // since the built-in formatter has problems editing partial documents
255         return mFormatGuiXml && mCustomXmlFormatter;
256     }
257 
258     /**
259      * Should the XML formatter use a custom Android XML formatter (following
260      * Android code style) or use the builtin Eclipse XML formatter?
261      *
262      * @return true if the Android formatter should be used instead of the
263      *         default Eclipse one
264      */
getUseCustomXmlFormatter()265     public boolean getUseCustomXmlFormatter() {
266         return mCustomXmlFormatter;
267     }
268 
269     /**
270      * Should the Android XML formatter use the Eclipse XML indentation settings
271      * (usually one tab character) instead of the default 4 space character
272      * indent?
273      *
274      * @return true if the Eclipse XML indentation settings should be use
275      */
isUseEclipseIndent()276     public boolean isUseEclipseIndent() {
277         return mUseEclipseIndent;
278     }
279 
280     /**
281      * Should the Android XML formatter try to avoid inserting blank lines to
282      * make the format as compact as possible (no blank lines between elements,
283      * no blank lines surrounding comments, etc).
284      *
285      * @return true to remove blank lines
286      */
isRemoveEmptyLines()287     public boolean isRemoveEmptyLines() {
288         return mRemoveEmptyLines;
289     }
290 
291     /**
292      * Should the Android XML formatter attempt to place a single attribute on
293      * the same line as the element open tag?
294      *
295      * @return true if single-attribute elements should place the attribute on
296      *         the same line as the element open tag
297      */
isOneAttributeOnFirstLine()298     public boolean isOneAttributeOnFirstLine() {
299         return mOneAttributeOnFirstLine;
300     }
301 
302     /**
303      * Returns the sort order to be applied to the attributes (one of which can
304      * be {@link AttributeSortOrder#NO_SORTING}).
305      *
306      * @return the sort order to apply to the attributes
307      */
getAttributeSort()308     public AttributeSortOrder getAttributeSort() {
309         if (mAttributeSort == null) {
310             return AttributeSortOrder.LOGICAL;
311         }
312         return mAttributeSort;
313     }
314 
315     /**
316      * Returns whether a space should be inserted before the closing {@code >}
317      * character in open tags and before the closing {@code />} characters in
318      * empty tag. Note that the {@link XmlFormatStyle#RESOURCE} style overrides
319      * this setting to make it more compact for the {@code <item>} elements.
320      *
321      * @return true if an empty space should be inserted before {@code >} or
322      *         {@code />}.
323      */
isSpaceBeforeClose()324     public boolean isSpaceBeforeClose() {
325         return mSpaceBeforeClose;
326     }
327 
328     /**
329      * Returns whether the file should be automatically formatted on save.
330      *
331      * @return true if the XML files should be formatted on save.
332      */
isFormatOnSave()333     public boolean isFormatOnSave() {
334         return mFormatOnSave;
335     }
336 
getBuildForceErrorOnNativeLibInJar()337     public boolean getBuildForceErrorOnNativeLibInJar() {
338         return mBuildForceErrorOnNativeLibInJar;
339     }
340 
getBuildSkipPostCompileOnFileSave()341     public boolean getBuildSkipPostCompileOnFileSave() {
342         return mBuildSkipPostCompileOnFileSave;
343     }
344 
getPaletteModes()345     public String getPaletteModes() {
346         return mPalette;
347     }
348 
setPaletteModes(String palette)349     public void setPaletteModes(String palette) {
350         mPalette = palette;
351 
352         // need to save this new value to the store
353         IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
354         store.setValue(PREFS_PALETTE_MODE, palette);
355     }
356 
getMonitorDensity()357     public float getMonitorDensity() {
358         return mMonitorDensity;
359     }
360 
setMonitorDensity(float density)361     public void setMonitorDensity(float density) {
362         mMonitorDensity = density;
363 
364         // need to save this new value to the store
365         IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
366         store.setValue(PREFS_MONITOR_DENSITY, density);
367     }
368 
369     /**
370      * Sets the new location of the SDK
371      *
372      * @param location the location of the SDK
373      */
setSdkLocation(File location)374     public void setSdkLocation(File location) {
375         mOsSdkLocation = location != null ? location.getPath() : null;
376 
377         // TODO: Also store this location in the .android settings directory
378         // such that we can support using multiple workspaces without asking
379         // over and over.
380         if (mOsSdkLocation != null && mOsSdkLocation.length() > 0) {
381             DdmsPreferenceStore ddmsStore = new DdmsPreferenceStore();
382             ddmsStore.setLastSdkPath(mOsSdkLocation);
383         }
384 
385         // need to save this new value to the store
386         IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
387         store.setValue(PREFS_SDK_DIR, mOsSdkLocation);
388     }
389 
390     @Override
initializeDefaultPreferences()391     public void initializeDefaultPreferences() {
392         IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
393         initializeStoreWithDefaults(store);
394     }
395 
initializeStoreWithDefaults(IPreferenceStore store)396     public void initializeStoreWithDefaults(IPreferenceStore store) {
397         store.setDefault(PREFS_BUILD_RES_AUTO_REFRESH, true);
398         store.setDefault(PREFS_BUILD_FORCE_ERROR_ON_NATIVELIB_IN_JAR, true);
399         store.setDefault(PREFS_BUILD_SKIP_POST_COMPILE_ON_FILE_SAVE, true);
400 
401         store.setDefault(PREFS_BUILD_VERBOSITY, BuildVerbosity.ALWAYS.name());
402 
403         store.setDefault(PREFS_HOME_PACKAGE, "android.process.acore"); //$NON-NLS-1$
404 
405         store.setDefault(PREFS_MONITOR_DENSITY, 0.f);
406         store.setDefault(PREFS_FORMAT_GUI_XML, true);
407         store.setDefault(PREFS_USE_CUSTOM_XML_FORMATTER, true);
408         store.setDefault(PREFS_ONE_ATTR_PER_LINE, true);
409         store.setDefault(PREFS_SPACE_BEFORE_CLOSE, true);
410 
411         // Defaults already handled; no need to write into map:
412         //store.setDefault(PREFS_ATTRIBUTE_SORT, AttributeSortOrder.LOGICAL.key);
413         //store.setDefault(PREFS_USE_ECLIPSE_INDENT, false);
414         //store.setDefault(PREVS_REMOVE_EMPTY_LINES, false);
415         //store.setDefault(PREFS_FORMAT_ON_SAVE, false);
416 
417         try {
418             store.setDefault(PREFS_DEFAULT_DEBUG_KEYSTORE,
419                     DebugKeyProvider.getDefaultKeyStoreOsPath());
420         } catch (KeytoolException e) {
421             AdtPlugin.log(e, "Get default debug keystore path failed"); //$NON-NLS-1$
422         } catch (AndroidLocationException e) {
423             AdtPlugin.log(e, "Get default debug keystore path failed"); //$NON-NLS-1$
424         }
425     }
426 }
427