1 /* 2 * Copyright (C) 2011 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 package com.android.ide.eclipse.adt.internal.editors.formatting; 17 18 import com.android.annotations.NonNull; 19 import com.android.annotations.Nullable; 20 import com.android.annotations.VisibleForTesting; 21 import com.android.ide.common.xml.XmlFormatPreferences; 22 import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; 23 import com.android.ide.common.xml.XmlAttributeSortOrder; 24 25 import org.eclipse.core.runtime.Preferences; 26 import org.eclipse.jface.preference.IPreferenceStore; 27 import org.eclipse.ui.internal.editors.text.EditorsPlugin; 28 import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; 29 import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; 30 import org.eclipse.wst.xml.core.internal.XMLCorePlugin; 31 import org.eclipse.wst.xml.core.internal.preferences.XMLCorePreferenceNames; 32 import org.w3c.dom.Attr; 33 34 import java.util.Comparator; 35 36 /** 37 * Formatting preferences used by the Android XML formatter. 38 */ 39 public class EclipseXmlFormatPreferences extends XmlFormatPreferences { 40 @VisibleForTesting 41 protected EclipseXmlFormatPreferences() { 42 } 43 44 /** 45 * Creates a new {@link EclipseXmlFormatPreferences} based on the current settings 46 * in {@link AdtPrefs} 47 * 48 * @return an {@link EclipseXmlFormatPreferences} object 49 */ 50 @NonNull 51 public static EclipseXmlFormatPreferences create() { 52 EclipseXmlFormatPreferences p = new EclipseXmlFormatPreferences(); 53 AdtPrefs prefs = AdtPrefs.getPrefs(); 54 55 p.useEclipseIndent = prefs.isUseEclipseIndent(); 56 p.removeEmptyLines = prefs.isRemoveEmptyLines(); 57 p.oneAttributeOnFirstLine = prefs.isOneAttributeOnFirstLine(); 58 p.sortAttributes = prefs.getAttributeSort(); 59 p.spaceBeforeClose = prefs.isSpaceBeforeClose(); 60 61 return p; 62 } 63 64 @Override 65 @Nullable 66 public Comparator<Attr> getAttributeComparator() { 67 // Can't just skip sorting; the attribute table moves attributes out of order 68 // due to hashing, so sort by node positions 69 if (sortAttributes == XmlAttributeSortOrder.NO_SORTING) { 70 return EXISTING_ORDER_COMPARATOR; 71 } 72 return sortAttributes.getAttributeComparator(); 73 } 74 75 private static final Comparator<Attr> EXISTING_ORDER_COMPARATOR = new Comparator<Attr>() { 76 @Override 77 public int compare(Attr attr1, Attr attr2) { 78 IndexedRegion region1 = (IndexedRegion) attr1; 79 IndexedRegion region2 = (IndexedRegion) attr2; 80 81 return region1.getStartOffset() - region2.getStartOffset(); 82 } 83 }; 84 85 // The XML module settings do not have a public API. We should replace this with JDT 86 // settings anyway since that's more likely what users have configured and want applied 87 // to their XML files 88 89 /** 90 * Returns the string to use to indent one indentation level 91 * 92 * @return the string used to indent one indentation level 93 */ 94 @Override 95 @SuppressWarnings({ 96 "restriction", "deprecation" 97 }) 98 public String getOneIndentUnit() { 99 if (useEclipseIndent) { 100 // Look up Eclipse indent preferences 101 // TODO: Use the JDT preferences instead, which make more sense 102 Preferences preferences = XMLCorePlugin.getDefault().getPluginPreferences(); 103 int indentationWidth = preferences.getInt(XMLCorePreferenceNames.INDENTATION_SIZE); 104 String indentCharPref = preferences.getString(XMLCorePreferenceNames.INDENTATION_CHAR); 105 boolean useSpaces = XMLCorePreferenceNames.SPACE.equals(indentCharPref); 106 107 StringBuilder indentString = new StringBuilder(); 108 for (int j = 0; j < indentationWidth; j++) { 109 if (useSpaces) { 110 indentString.append(' '); 111 } else { 112 indentString.append('\t'); 113 } 114 } 115 mOneIndentUnit = indentString.toString(); 116 } 117 118 return mOneIndentUnit; 119 } 120 121 /** 122 * Returns the number of spaces used to display a single tab character 123 * 124 * @return the number of spaces used to display a single tab character 125 */ 126 @Override 127 @SuppressWarnings("restriction") // Editor settings 128 public int getTabWidth() { 129 if (mTabWidth == -1) { 130 String key = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH; 131 try { 132 IPreferenceStore prefs = EditorsPlugin.getDefault().getPreferenceStore(); 133 mTabWidth = prefs.getInt(key); 134 } catch (Throwable t) { 135 // Pass: We'll pick a suitable default instead below 136 } 137 if (mTabWidth <= 0) { 138 mTabWidth = 4; 139 } 140 } 141 142 return mTabWidth; 143 } 144 } 145