| package org.jetbrains.android.dom.converters; |
| |
| import com.android.SdkConstants; |
| import com.android.annotations.VisibleForTesting; |
| import com.intellij.psi.xml.XmlElement; |
| import com.intellij.util.containers.HashMap; |
| import com.intellij.util.xml.ConvertContext; |
| import com.intellij.util.xml.ResolvingConverter; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.*; |
| |
| /** |
| * @author Eugene.Kudelevsky |
| */ |
| public class DimensionConverter extends ResolvingConverter<String> implements AttributeValueDocumentationProvider { |
| public static final DimensionConverter INSTANCE = new DimensionConverter(); |
| |
| private static final Map<String, String> ourUnits = new HashMap<String, String>(); |
| |
| static { |
| ourUnits.put(SdkConstants.UNIT_DP, "<b>Density-independent Pixels</b> - an abstract unit " + |
| "that is based on the physical density of the screen."); |
| ourUnits.put(SdkConstants.UNIT_SP, "<b>Scale-independent Pixels</b> - this is like the dp unit, " + |
| "but it is also scaled by the user's font size preference."); |
| ourUnits.put(SdkConstants.UNIT_PT, "<b>Points</b> - 1/72 of an inch based on the physical size of the screen."); |
| ourUnits.put(SdkConstants.UNIT_MM, "<b>Millimeters</b> - based on the physical size of the screen."); |
| ourUnits.put(SdkConstants.UNIT_IN, "<b>Inches</b> - based on the physical size of the screen."); |
| ourUnits.put(SdkConstants.UNIT_PX, "<b>Pixels</b> - corresponds to actual pixels on the screen. Not recommended."); |
| } |
| |
| @NotNull |
| @Override |
| public Collection<? extends String> getVariants(ConvertContext context) { |
| final XmlElement element = context.getXmlElement(); |
| |
| if (element == null) { |
| return Collections.emptyList(); |
| } |
| final String value = ResourceReferenceConverter.getValue(element); |
| |
| if (value == null) { |
| return Collections.emptyList(); |
| } |
| final String intPrefix = getIntegerPrefix(value); |
| |
| if (intPrefix.isEmpty()) { |
| return Collections.emptyList(); |
| } |
| final List<String> result = new ArrayList<String>(ourUnits.size()); |
| |
| for (String unit : ourUnits.keySet()) { |
| result.add(intPrefix + unit); |
| } |
| return result; |
| } |
| |
| @Nullable |
| @Override |
| public String fromString(@Nullable @NonNls String s, ConvertContext context) { |
| final String unit = getUnitFromValue(s); |
| |
| if (unit == null || unit.isEmpty()) { |
| return null; |
| } |
| if (SdkConstants.UNIT_DIP.equals(unit)) { |
| return s; |
| } |
| return ourUnits.get(unit) != null ? s : null; |
| } |
| |
| @Nullable |
| @Override |
| public String toString(@Nullable String s, ConvertContext context) { |
| return s; |
| } |
| |
| @Override |
| public String getErrorMessage(@Nullable String s, ConvertContext context) { |
| final String unit = getUnitFromValue(s); |
| if (unit != null && !unit.isEmpty()) { |
| if (unit.startsWith(",")) { |
| return "Use a dot instead of a comma as the decimal mark"; |
| } |
| return "Unknown unit '" + unit + "'"; |
| } |
| return super.getErrorMessage(s, context); |
| } |
| |
| @Nullable |
| public static String getUnitFromValue(@Nullable String value) { |
| if (value == null) { |
| return null; |
| } |
| final String intPrefix = getIntegerPrefix(value); |
| |
| if (intPrefix.isEmpty()) { |
| return null; |
| } |
| return value.substring(intPrefix.length()); |
| } |
| |
| @VisibleForTesting |
| @NotNull |
| static String getIntegerPrefix(@NotNull String s) { |
| if (s.length() == 0) { |
| return ""; |
| } |
| final StringBuilder intPrefixBuilder = new StringBuilder(); |
| |
| for (int i = 0; i < s.length(); i++) { |
| final char c = s.charAt(i); |
| |
| if (!Character.isDigit(c) && c != '.' && (i > 0 || c != '-')) { |
| break; |
| } |
| intPrefixBuilder.append(c); |
| } |
| return intPrefixBuilder.toString(); |
| } |
| |
| @Override |
| public String getDocumentation(@NotNull String value) { |
| final String unit = getUnitFromValue(value); |
| |
| if (unit == null) { |
| return null; |
| } |
| final String description = ourUnits.get(unit); |
| |
| if (description == null || description.length() == 0) { |
| return null; |
| } |
| return "<html><body>" + description + "</body></html>"; |
| } |
| } |