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