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_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 
    103         BuildVerbosity(int level) {
    104             mLevel = level;
    105         }
    106 
    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          */
    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 
    130     public static void init(IPreferenceStore preferenceStore) {
    131         sThis.mStore = preferenceStore;
    132     }
    133 
    134     public static AdtPrefs getPrefs() {
    135         return sThis;
    136     }
    137 
    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      */
    234     public synchronized String getOsSdkFolder() {
    235         return mOsSdkLocation;
    236     }
    237 
    238     public synchronized BuildVerbosity getBuildVerbosity() {
    239         return mBuildVerbosity;
    240     }
    241 
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    333     public boolean isFormatOnSave() {
    334         return mFormatOnSave;
    335     }
    336 
    337     public boolean getBuildForceErrorOnNativeLibInJar() {
    338         return mBuildForceErrorOnNativeLibInJar;
    339     }
    340 
    341     public boolean getBuildSkipPostCompileOnFileSave() {
    342         return mBuildSkipPostCompileOnFileSave;
    343     }
    344 
    345     public String getPaletteModes() {
    346         return mPalette;
    347     }
    348 
    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 
    357     public float getMonitorDensity() {
    358         return mMonitorDensity;
    359     }
    360 
    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      */
    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
    391     public void initializeDefaultPreferences() {
    392         IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore();
    393         initializeStoreWithDefaults(store);
    394     }
    395 
    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